泛型(JDK1.5新特性)(四)

本文详细介绍了Java泛型的使用方法、好处、注意事项、高级特性(如通配符)、自定义泛型方法和类的实现,以及如何在反射中获取泛型类型的实际参数。内容涵盖从基础到高级的全面解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


------------------------------------------入门-----------------------------------------------------------------

1.传统集合不使用泛型的后果?

 (1)取数据时需要对类型进行转换

 (2)难以确定取出数据的确切类型

2.使用泛型的好处?

 (1)指定集合可以容纳的数据类型;

 (2)如果放入的数据类型错误,编译时会报错;

 (3)不需要类型转换,如果接收类型不对,编译时也会报错

 总之,使用它会让关于类型的错误在编译时期就被发现。

3.泛型不但可以使用在集合中,也可以使用在其它地方,比如Constructor<String>

4.去类型化

    泛型信息是提供给编译器的,编译完泛型消失,JVM无法知道,所以,如果是两个ArrayList对象,使用了不同泛型,那么在运行时,它们的字节码还是同一份;而且使用反射技术可以在程序运行期间给集合里添加任意类型;

5.泛型中的术语:

  ArrayList称为原始类型

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

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

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

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

  ArrayList<Integer>中的<>typeof

 

6.注意事项:

  (1)如果等号两边都使用泛型,那么泛型必须一致,如如果左边是<String>,那么右边必须是<String>

   (2)下面的方式正确:

     Collection<String> c = new Vector();

     Collection c = new Vector<String>()

  (3)编译器不允许创建泛型变量的数组;

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

--------------------------------------------------高级(?通配符)------------------------------------

1.?通配符可以接受任意类型:

  如定义一个方法可以打印任何泛型的set集合元素的方法private void print(Set<?> set){

    .......

}

那么此方法可以接受任何泛型类型的set集合及其子类集合;

但是代码中不允许出现诸如set.add();这类与类型有关的方法,因为在我们编写源文件时?类型是不确定的。

 

2. 泛型上下限:

 List<? super Integer> x表示右边可以接收的泛型类型是Integer的父类或Integer

 List<? extends Number> x 表示右边可以接受的泛型是Number以及其子类;

 

 如:List<? super Integer> x = new ArrayList<Number>();

     List<? extends Number> x = new ArrayList<Integer>();

问题:下面的两种定义方式在使用泛型和定义泛型类或方法时都能使用吗?

      ?可以被换做T吗?

--------------------------------------------自定义泛型方法------------------------------------------------

1.泛型推断:

  下面的代码T取得是xy类型的最小父类(泛型推断),因为此方法可以这样的调用(2,String),那么T就是Object,但是以下的代码没有意义;

<T> T add(T x,T y) {

return null;

}

2.T只可以是引用类型:

  void  add(T x)-->add(1)-->1会被自动装箱

  void  print(T[] x)-->print(new int[]{1,2,3})-->此调用错误

3.泛型方法实例:

 public  static<K,F> F void print(K k){

     System.out.println(k);

     return  (F)new Object();

}

 

说明:(1)泛型必须先使用<>声明再使用;

     (2)泛型K的具体类型由方法调用时传入的参数类型决定

      (3)泛型F的具体类型由方法调用时接收返回值的变量的类型决定;

     (4)可以使用多个泛型,多个泛型在一个<>里声明

---------------------------------------------------自定义泛型类-------------------------------------------

1.自定义泛型类就是就是在类名后面加了泛型声明的类。

2.如何定义:

  Class  XxxDao{

  public void <T>add(T t){...}

  public <T> T get(){...} 

}

如果XxxDao的对象创建时,只希望对一种类型进行操作,那么就不能使用上面的定义,因为两个T是互不相干的,为了让它们有联系,必须把T的声明加在类的后面

 Class  XxxDao<T>{

  public void  add(T t){...}

  public T get(){...} 

}

上面的类就是一个泛型类

如果存在一个静态方法也使用泛型 ,那么静态方法的泛型要单独声明;

 Class  XxxDao<T>{

  public void  add(T t){...}

  public T get(){...} 

  public static <T> void  doSome(T t){...}//注意此行的T和类上的T没有任何关系,类上的T是给对象用的

}

如果一个方法里存在多个泛型,

 Class  XxxDao<T,E>{

  public void  add(T t){...}

  public E findById(int id){...} 

}

 

--------------------------------------反射泛型类型的实际参数-----------------------------------------------

1.如何获取实际类型参数?

想要的得到类型化的类型(如ArrayList<Integer>)的实际类型参数(Integer),无法通过ArrayList的字节码获取,只能把ArrayList<Integer>作为一个方法的参数或者返回值类型,使用Method提供的方法来获取。

小插曲:因为去类型化的缘故,下面的方法不是重载

2.实际代码:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值