黑马程序员:Java基础总结



泛型(高级)

 
ASP.Net+Android+IO开发

.Net培训
、期待与您交流!




泛型(高级)

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。

去类型化
            ArrayList<String> arr1 = 
new 
ArrayList<String>();
            ArrayList<Integer> arr2 = 
new 
ArrayList<Integer>();
            System. 
out
.println(arr1.getClass() == arr2.getClass());
// true
用反射越过泛型限制
            arr2.getClass().getMethod( 
"add"
, Object.
class
).invoke(arr2, 
"wanqi"
);
            System. 
out
.println(arr2);

泛型术语

整个称为ArrayList<E>
泛型类型

ArrayList<E>中的E称为类型变量或
类型参数

整个ArrayList<Integer>称为
参数化的类型

ArrayList<Integer>中的Integer称为类型参数的实例或
实际类型参数

ArrayList<Integer>中的<>念着typeof

ArrayList称为
原始类型


参数化类型与原始类型的兼容性

参数化类型可以引用一个原始类型的对象,编译报告警告,例如,Collection<String> c = new Vector();//可不可以,不就是编译器一句话的事吗?

原始类型可以引用一个参数化类型的对象,编译报告警告,例如,Collection c = new Vector<String>();//原来的方法接受一个集合参数,新的类型也要能传进去


参数化类型不考虑类型参数的继承关系:

Vector<String> v = new Vector<Object>(); //错误!///不写<Object>没错,写了就是明知故犯

Vector<Object> v = new Vector<String>(); 
//也错误!

可以使用通配符显示继承关系
限定通配符的上边界:限定通配符总是包括自己。

正确:Vector<? extends Number> x = new Vector<Integer>();


限定通配符的下边界:

正确:Vector<? super Integer> x = new Vector<Number>();



编译器不允许创建泛型变量的数组。
即在创建数组实例时,数组的元素不能使用参数化的类型,
例如,下面语句有错误:

     Vector<Integer> vectorList[] = new Vector<Integer>[10];

泛型中的?通配符
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。

?表示的是任意的同一类型参数
Class<?> y = Class.forName(
"java.lang.String" 
);
Class<String> x = Class.forName(
"java.lang.String"
);
//错误
Class<String> x = Class<?> y; 
//错误

限定通配符的上边界:

正确:Vector<? extends Number> x = new Vector<Integer>();

错误:Vector<? extends Number> x = new Vector<String>();


限定通配符的下边界:

正确:Vector<? super Integer> x = new Vector<Number>();

错误:Vector<? super Integer> x = new Vector<Byte>();

泛型集合类的综合

            HashMap<String, Integer> hm = 
new 
HashMap<String, Integer>();
            hm.put( 
"wanqi"
, 18);
            hm.put( 
"zhanwen"
, 28);
            Set<Map.Entry<String, Integer>> set = hm.entrySet();
             
for 
(Map.Entry<String, Integer> entry : set) {
                  entry.getKey();
                  entry. getValue();
            }


自定义泛型

定义泛型方法
是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。
如:public static <T> void demo(T a,T b){}

public 
static 
void 
main(String[] args) 
throws 
Exception {
             f(1);
             f(
'a'
);
             f(1.1);
             f(
""
);
             f(
new 
int
[1]);

      }

       
public 
static 
<T> 
void 
f(T a) {
            System. 
out
.println(a.getClass().getName());
      }
//结果:
//java.lang.Integer
//java.lang.Character
//java.lang.Double
//java.lang.String
//[I

需注意操作:
1,自定义泛型方法,不一定可以想加
       
public 
<T> T add (T a,T b){
             
//return a+b; 未定义方法
             
return 
null 
;
      }
2,只有引用类型才能作为泛型方法的实际参数
      
swap(new int[3],3,5);语句会报告编译错误。
3,普通方法、构造方法和静态方法中都可以使用泛型。

4,也可以用类型变量表示异常,称为参数化的异常,可以用于方法的throws列表中,但是不能用于catch子句中。


5,在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分,例如:


      
public static <K,V> V getValue(K key) { return map.get(key);}


泛型方法的练习题
1,编写一个泛型方法,自动将Object类型的对象转换成其他类型。
      
public 
static 
<T> T auto(Object obj) { 
return 
(T) obj; }
2,采用自定泛型方法的方式打印出任意参数化类型的集合中的所有内容。
       
public 
static 
<E> 
void 
print(Collection<E> cols) {
             
for 
(E obj : cols) {
                  System. 
out
.println(obj);
            }
      }
3,定义一个方法,把任意参数类型的集合中的数据安全地复制到相应类型的数组中。
       
public 
static 
<T> 
void 
copy(Collection<T> col, T[] arr) {
             
for 
(
int 
i = 0; i < arr.
length
; i++) {
                   col.add(arr[i]);
            }
      }

类型参数的类型推断
编译器判断范型方法的实际类型参数的过程称为类型推断,类型推断是相对于知觉推断的,其实现方法是一种非常复杂的过程。

根据调用泛型方法时实际传递的参数类型或返回值的类型来推断,具体规则如下:
1,
当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被应用了,那么根据调用方法时该处的实际应用类型来确定,这很容易凭着感觉推断出来,即直接根据调用方法时传递的参数类型或返回值来决定泛型参数的类型
2,
当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型都对应同一种类型来确定,这很容易凭着感觉推断出来
3,
当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时候取多个参数中的最大交集类型,
4,
当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型, 并且使用返回值,这时候优先考虑返回值的类型
5,
参数类型的类型推断具有传递性,下面第一种情况推断实际参数类型为Object,编译没有问题,而第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型



定义泛型类型
如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型

class 
Demo<T>{
       
private 


;
       
public 
T getA() {
             
return 

;
      }
       
public 
void 
setA(T a) {
             
this
.

= a;
      }
}

注意:

在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。

当一个变量被声明为泛型时,只能被实例变量、方法和内部类调用,而
不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数


通过反射获得泛型的参数化类型

Method getDeclaredMethod(String name, Class<?>... parameterTypes)
          返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
Type[] getGenericParameterTypes()
          按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的。

接口 ParameterizedType  extends Type

方法摘要

 Type[] getActualTypeArguments()
          返回表示此类型实际类型参数的 Type 对象的数组。
 Type getOwnerType()
          返回 Type 对象,表示此类型是其成员之一的类型。
 Type getRawType()
          返回 Type 对象,表示声明此类型的类或接口。

       
private 
Vector<Date> 
dates 

new 
Vector<Date>();

       
public 
void 
setDates(Vector<Date> dates) {
             
this
.
dates 
= dates;
      }

       
public 
static 
void 
main(String[] args) 
throws 
Exception {
            Method method = Ts0. 
class
.getMethod(
"setDates" 
, Vector.
class
);
            ParameterizedType pType = (ParameterizedType) method
                        .getGenericParameterTypes()[0];
            System. 
out
.println(
"setDates(" 
+ ((Class) pType.getRawType()).getName()
                        + 
"<" 
+ ((Class) (pType.getActualTypeArguments()[0])).getName()
                        + 
">)"
);
      }




 
ASP.Net+Android+IO开发

.Net培训
、期待与您交流!

黑马程序员:Java基础总结----泛型(高级)的更多相关文章

  1. 黑马程序员——JAVA基础之泛型和通配符

    ------- android培训.java培训.期待与您交流! ---------- 泛型:            JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. 泛型好处: ...

  2. 黑马程序员----java基础笔记中(毕向东)

    <p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...

  3. 黑马程序员Java基础班+就业班课程笔记全发布(持续更新)

    正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G  QQ 1481135711 这是我总 ...

  4. 黑马程序员----java基础笔记上(毕向东)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 笔记一共记录了毕向东的java基础的25天课程,分上.中.下 本片为上篇,涵盖前10天课程 1. ...

  5. 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象

    ------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...

  6. 黑马程序员——JAVA基础之语法、命名规则

    ------- android培训.java培训.期待与您交流! ---------- 1.java语言组成:关键字,标识符,注释,常量和变量,运算符,语句,函数,数组. 2.java关键字:被Jav ...

  7. 黑马程序员——JAVA基础之JDK1.5新特性高级for循环和可变参数

    ------- android培训.java培训.期待与您交流! ---------- 高级for循环   格式: for(数据类型 变量名 : 被遍历的集合(Collection)或者数组) {   ...

  8. 黑马程序员——JAVA基础之File类,递归,打印流,合并切割流

    ------- android培训.java培训.期待与您交流! ---------- File类 用来将文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作. File对象可以作为参数传递 ...

  9. 黑马程序员——JAVA基础之多线程的安全问题

    ------- android培训.java培训.期待与您交流! ---------- 导致多线程出现问题的一个特殊的状态:就绪.具备了执行资格,但是还没有获取资源. 导致安全问题的出现的原因: 1. ...

  10. 黑马程序员——JAVA基础之简述设计模式

    ------- android培训.java培训.期待与您交流! ---------- 设计模式(Design Patterns) 设计模式(Design pattern)是一套被反复使用.多数人知晓 ...

随机推荐

  1. OCP-1Z0-042-V12.39-51题

    51.Which two statements regarding archive log destinations are true? 题目解析: A(正确)因为:.归档日志最多可以配置10个 B和 ...

  2. 正确处理Windows电源事件

    简介为系统挂起与恢复而进行的应用准备步骤 曾几何时,当您正要通过应用提交或发布一些重要数据时,突然遇到一些急事需要处理,而且会耽误很长时间.当您完成任务回到电脑前时,发现电脑已经自动进入 了挂起状态, ...

  3. WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用

    原文:WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经> ...

  4. codeforces 148D 概率DP

    题意: 原来袋子里有w仅仅白鼠和b仅仅黑鼠 龙和王妃轮流从袋子里抓老鼠. 谁先抓到白色老师谁就赢. 王妃每次抓一仅仅老鼠,龙每次抓完一仅仅老鼠之后会有一仅仅老鼠跑出来. 每次抓老鼠和跑出来的老鼠都是随 ...

  5. Spring 从零開始-05

    最终能到Spring的AOP编程了,AOP的概念特别的多.所以须要你在開始之前有点了解,然后通过代码慢慢学习! - 切面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象.事务管 ...

  6. android 设置字体颜色、EditText自己主动输入转换成大写字母的多种方式

    在TextView上面设置某一个字的字体颜色为指定颜色时,能够通过java类SpannableString类和Html语言来实现. (一)SpannableString类方式 private void ...

  7. Canvas上绘制几何图形

    重要的类自定义View组件要重写View组件的onDraw(Canvase)方法,接下来是在该 Canvas上绘制大量的几何图形,点.直线.弧.圆.椭圆.文字.矩形.多边形.曲线.圆角矩形,等各种形状 ...

  8. 引用iscroll的一个封装方法

    var Page = function(cid, data,callback) { var _self = this; var cid = $(cid); var currPage=1; // 下拉上 ...

  9. jquery mobile -role

    jquery mobile -role - cc_jony - 博客园 jquery mobile -role   data-page 页面 data-header 页面的头部 data-conten ...

  10. spring Jdbc自己主动获取主键。

    学习了下springjdbc,感觉挺有用的,相对来说springjdbc 扩展性相当好了 package com.power.dao; import java.lang.reflect.Paramet ...