五分钟了解Java泛型(上)

泛型概述

数组与集合

  • Java中可以定义任意类型的属性,例如String[]中存放的就是String类型的数据,我们称之为持有String类型的数组。但1.5之前时,Java的集合类却只能持有Object类型,1.5时添加了泛型的概念,泛型允许Java创建持有任意类型的集合对象,例如:new ArrayList<String>()表示这个ArrayList中只能持有String类型的对象。

类型变量(参数)

  • 具有一个或多个类型参数的类就是泛型类。
    泛型类都至少有一个类型变量,你需要在创建泛型类对象时给类型变量赋值。当然,你要给类型变量赋的值必须是一个类型!
ArrayList<String> arr = new ArrayList<String>();
  • 其中String就是给ArrayList类的类型变量赋值。在ArrayList类中所有使用类型变量的地方都会被String所替换。例如:boolean
    add(E e),其中e的类型就是变量,它会被String替换,最终变成boolean add(String e)。E get(int
    index)方法中返回值的类型为变量,它也会被String替换,最终变成String get(int index)。

泛型的好处

  • 将运行期遇到的问题转移到了编译期。例如在1.4时,ArrayList类的add()方法参数还是Object类型,当然get()方法的返回值类型也是Object。这就说明使用get()方法获返回值后,你还需要强转。错误的强转可能会出现ClassCastException。
ArrayList list = new ArrayList();
list.add(“hello”);
Integer i = (Integer)list.get(0);//抛出异常

这个问题在有了泛型之后就不会再有了。

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(“hello”);//编译出错!
Integer i = (Integer)list.get(0);

很明显,是泛型把只能在运行时才能找到的错误推向了编译期!这就是泛型的优点!!!

定义泛型类(接口)

自定义泛型类的语法

  • 自定义泛型类的语法基本与定义正常的法一样:
    public class A<T> {}。定义泛型类时,需要在类名后面给出一对尖括号,在尖括号中给出1~N个类型变量。

泛型类中使用类型变量

  • 用户在使用泛型类时,需要为类型变量赋值。例如:new A()。在泛型类中可以使用类型变量:
public class A<T> {
    private T t;
    public A(T t) {
        this.t = t;
}
public T get() {
    return t;
}
}
  • 当用户创建A类对象时,就会给A类的类型变量T赋值,例如:new A<String>(),这说明在A类中所有的T都会被String替换。
public class A {
    private String t;
    public A(String t) {
        this.t = t;
}
public String get() {
    return t;
}
}

类型变量的限制

  • 上例中,A类中定义了T类型的属性t,这个属性t的类型是一个变量,无法确定的,因为你在定义A类时,根本就不知道用户会传递什么类型给T,所以你也不能调用属性t的方法,因为你不知道t的类型,就不知道它有什么方法。但是,我们知道任何类都是Object类的子类,那么就说明你可以调用属性t的Object中存在的方法。
  • 注意,你不能使用T类型的构造器:new T(),因为你不能确定t的类型,那么也就不知道它有什么样的构造器,甚至是否有public构造器,所以不能创建。
  • 相同的道理,也不能创建T类型的属性,例如:new T[10],这也是不行的!还有一点,在泛型类中,static方法中不能使用类型变量T。

继承(实现)泛型类(接口)

继承泛型类之一

  • 如果当前类是泛型类,那么在继承(实现)泛型类(接口)时,可以把自己的类型变量传递给父类(接口)。
public class ArrayList<E> implements List<E> {  }
  • 可以这样来理解,其中public class ArrayList<E>中的<E>表示定义了一个泛型类,其中E是定义的类型变量,而implements List<E>中的<E>表示给List接口传递<E>,这是在使用变量类型E,而不是在定义了。
ArrayList<String> arr = new ArrayList<String>();
  • 在用户创建ArrayList类对象时,传递给ArrayList类中的E的值是String,那么ArrayList会把这个String再传递给List中的E。
  • 你可能会想,为什么一定要给父类或接口传递类型变量。那我会问你,实现类不给List接口中的E来赋值,谁来给它赋值?难道你想new List<String>()这样赋值么?接口是不能被实例化的,你只能让实现类来赋值,你不赋值,接口中的get()方法一直返回E类型!!!

继承泛型类之二

  • 泛型类的子类不一定必须为泛型类,也可以是非泛型类。这时因为子类没有类型变量可以传递给父类,那么也就能传递给父类类型常量了。
public class String implements Comparable<String> {
    public int compareTo(String other) {}
}
  • 这时,再重写父类中方法时,所有的类型变量都是String了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值