黑马程序员———泛型

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


 

ArrayList<E>  整个称为泛型类型
ArrayList<E>  E称为类型变量或者类型参数
ArrayList<Integer>整个称为参数化的类型
ArrayList<E>   Integer称为类型参数的实例或者实际类型参数
ArrayList<E>  <>念着type  of
ArrayList  称为原始类型


参数化类型和原始类型的兼容性。
Collection<String> c = new Vector();
Collection c = new Vector<String>();


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

Vector<String> c = new Vector<Obejct>();
Vector<Obejct> c = new Vector<String>();
都错误。

创建数组时,数组的元素不能使用参数化的类型。

Vector<Integer> vectorList[] = new Vector<String>[10];
错误。

Vector v1 = new Vector<String>();
Vector<Object< v=v1;
错误。


======================


泛型的通配符扩展应用:
错误方式:
public static void printCollection(Collection<Object> collection)
{
 for(Object obj:cols)
 {
  System.out.println(obj);
 }
 cols.add("string");//没错
 //cols = new HashSet<Date>();//会报告错误
}

正确方式:
public static void printCollection(Collection<?> collection)
{
 for(Object obj:cols)
 {
  System.out.println(obj);
 }
 //cols.add("string");//错误
 cols.size();//此方法与类型参数没有关系
 cols = new HashSet<Date>();
}


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


=========================
泛型中的?通配符的扩展

限定通配符的上边界:
true:Vector<? extends Number> x=new Vector<Integer>();
false:Vector<? extends Number> x=new Vector<String>();

? extends Number 表示Number以及子类
Number有8个基本数据类型
String不是Number以及子类,所以不行。


限定通配符的下边界:
true:Vector<? super Integer> x=new Vector<Number>();
false:Vector<? super Integer> x=new Vector<Byte>();

? super Integer  表示Integer或者它的父类。
Byte是平级的,不是父类。


提示:限定通配符总是包括自己。


================

由C++模板函数引入自定义函数

只写一个函数可以适应各种类型

template<class T>
T add(T x,T y){
 return(T) (x+y);
}


java中的泛型类型类似于C++模板,但仅局限于表面。
java语言的泛型基本上完全是在编译器实现,用于编译器
类型检查和类型推断,然后生成普通的非泛型的字节码。
这种实现技术叫做擦除。(编译器使用泛型类型信息保证
类型安全,然后在生成字节码之前将其清除)

public static <T> int add(T a,T b)
{
 return null;
}
//任意类型必须在返回值之前

add(3,6);//装箱成Integer。
Number x1=add(3.5,5);
Object x2=add(3,"adg");


Set集合的Map.Entry方法:
Map<String,Integer> maps = new HashMap<String,Integer>();
maps.add("haha",22);
maps.add("wawa",44);

Set<Map.Entry<String,Integer>> entrys = maps.entrySet()
for(Map.Entry<String,Integer> entry : entrys) {
 syso:entry.getKey()+":"+entry.getValue();
}

===========================

写一个程序可以交换数组两个元素的位置
private static void swap(T[] a,int i, int j)
{
 T temp=a[i];
 a[i]=a[j];
 a[j]=temp;
}

swap(new String[]{"abc","yz"},1,2);
//swap(new int[][3],3,5);
//语句会报告编译错误
只有引用类型才能作为泛型方法的实际参数。

为什么不会对new int[3]的int自动装箱和拆箱呢,
因为new int[3]本身就是对象了,你想要的可能就是
int数组,它装箱不就弄巧成拙。
而上面add(3,5);使用基本数据类测试没问题,因为
自动装箱和拆箱。

--------------------------------------------

在定义泛型时也可以用extends限定符。

Class.getAnnotation()方法的定义。并且可以用&来
指定多个边界。如:<V extends Serializable&cloneable>
void method(){}。

普通方法,构造方法,静态方法都可以使用泛型。

也可以用型变量表示异常,称为参数化的异常,可以
用于方法的throws列表中,但是不能用于catch字句中。
private static <T extends Exception>void sayHello() throws T {
 try{}
 catch(Exception e){
  throw (T)e;


在泛型中可以同时有多个类型参数,在定义他们的尖括号中
用逗号分,例如:
public static <K,V> getValue(key){return map.get(key);}


根据调研泛型方法时传递的参数类型和返回值类型来推断,

如果类的实例对象中的多处要用到同一个泛型参数,既这些地方引用的泛型类型要保存
同一个实际类型时,这时候要采用泛型类型的方式进行定义,也就是类级别
的泛型。
public class GenericDao<T> {
 private T field1;
 public vod save(T obj){}
 public T getById(int id){}
}


注意:在对泛型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态
方法和静态变量调用。因为静态成员是被所有参数化的类所共享,所以静态成员
不应该有类级别的类型参数。

类中只有一个方法需要使用泛型,是使用类级别的泛型,
还是使用方法级别的泛型?选择类级别的。

 

 

 

 

 


 

 

 

 

 

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值