JavaSE学习笔记--泛型

 

泛型:

 

泛型是java jdk1.5出现的新特性之一。

泛型是给编译看的,当传入的实参类型不符时,会在编译期报错。而反射可以绕过编译器。

ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:

 整个ArrayList<E>称为泛型类型
  ArrayList<E>中的E称为类型变量或类型参数
 整个ArrayList<Integer>称为参数化的类型
  ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
  ArrayList<Integer>中的<>念做typeof
 ArrayList称为原始类型

参数化类型与原始类型的兼容性:
如下面的两个都是可以的,但是编译时会出现一个警告。
 Collection<String> c = new Vector();
 Collection c = new Vctor<String>();
参数化类型不考虑类型参数的继承关系:
 Collection<String> c = new Vector<Object>(); -->(错)
 Collection<Object> c = new Vector<String>(); -->(错)
在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:
 Vector<Integer> vectorList[] = new Vector<Integer>[10];
思考一下:下面的代码会报错吗?
 Vector v1 = new Vector<String>();
 Vector<Object> v = v1;
上面的不会报错。

泛型中的通配符: ?
在使用通配符泛型类型作为一个方法的参数列表时,此方法体中就不能再使用和类型有关的方法。只能使用与参数类型不管的方法,否侧的话会报错。
如下:
public static void printCollection(Collection<?> collection){
 //collection.add(1); (错的,不可以。因为1使用了指定的类型)
 collection.size();  //可以
 for(Object obj : collection){
  System.out.println(obj);
 } //可以
 collection = new HashSet<Date>(); //可以
}(较有效)
但是此时可以使用“通配符的方法”来克服这个弊端:<T>
如下:
public static void printCollection(Collection<T> collection, T obj){
 collection.add(obj); //这时,是可以的
 collection.size();  //可以
 for(Object obj : collection){
  System.out.println(obj);
 } //可以
 collection = new HashSet<Date>(); //可以


通配符的扩展
限制通配符的上边界:
 正确: 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>();

Float x1 = add(3.5,3); ( 错 )。
此时的编译器提示信息“Type nismatch: cannot convert from Number&Comparable<?> to Float”。
所以需要实现Comparble的Number,所以只能是Number类。所以只能改成下边这样。
Number x1 = add(3.5,3);
但是问题出现了,你会发现Number类并没有实现Comparable接口,而是只实现了Serializable接口。不知道这个是怎么解释的呢?

类型推断具有传播性,通过下边的例子就可以看出来了:
 copy1(new Vector<String>(), new String[10]);
 copy2(new Date[10],new String[10]);   //都取他们的交集类,即Object类
 copy1(new Vector<Date>(),new String[10]); //此时会报错,因为此时Date被泛型修饰无法再提升到父类Object

 public static <T> void copy1(Collection<T> dest, T[] src){
  for(int x=0; x<src.length; x++){
   dest.add(src[x]);
  }

 

---------------------- <a href="http://edu.csdn.net/heima" target="blank">android培训</a>、<a href="http://edu.csdn.net/heima" target="blank">java培训</a>、期待与您交流! ----------------------

 }
 public static <T> void copy2(T[] dest, T src){
  for(T t : dest){
   t = src;
  }
 }

自定义泛型类(类级别的泛型):
 其目的就是当我的类中有多个方法用到的泛型都是同一个类型,
而我们有想让这两个类型相同,就可以给这个类定义上这个泛型。这也是泛型类的由来。

注意静态方法中不能使用泛型。
class Person<E>
{
 public static void update(E obj){}
} (报错)
这是需要把他独立出来,单独使用“方法级别的泛型”
class Person<E>
{
 public static <E> void update(E obj){}
} (对)

对于泛型,java在编译之后就会去类型化。下边的两个方法不是重载。
public static void applyVector(Vector<Date> v1){

}
public static void applyVector(Vector<Integer> v1){

}

通过反射获取泛型的实际类型参数:(高级)
其思路是这样的,我们无法通过一个变量的数据是无法知道自己是什么类型的。
只能通过把这个变量作为一个参数传递给方法,通过泛型方法来知道参数列表中的泛型类型的。
代码如下:
//Vector<Date> v1 = new Vector<Date>();
 Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
 Type[] types = applyMethod.getGenericParameterTypes();
 ParameterizedType pType = (ParameterizedType)types[0];
 System.out.println(pType.getRawType());
 System.out.println(pType.getActualTypeArguments()[0]);

阅读更多
个人分类: 学习笔记
想对作者说点什么? 我来说一句

1.JavaSE基础学习笔记

2018年06月11日 606KB 下载

javase学习笔记(全)

2018年02月23日 777KB 下载

JAVASE学习笔记

2017年03月14日 302KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭