13. 泛型
引入泛型:下列代码在list集合中添加了三个Dog对象,然后添加一个Cat对象,然后循环遍历输出list集合Dog对象信息,但是因为有一个Cat对象,所以在向下转型时会抛出一个ClassCastException(类转换异常),
public class Generic01 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Dog("大黄",17));
list.add(new Dog("小黄",7));
list.add(new Dog("老黄",47));
list.add(new Cat("招财猫",7));
for (Object o : list) {
Dog dog = (Dog) o;
System.out.println(dog.toString());
}
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Cat{
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
}
- 不能对加入到集合ArrayList中的数据进行约束(不安全)
- 遍历的时候,需要进行类型转换,如果集合中的数据量很大,影响效率
引入异常后:
public class Generic01 {
public static void main(String[] args) {
ArrayList<Dog> list = new ArrayList<Dog>();
list.add(new Dog("大黄",17));
list.add(new Dog("小黄",7));
list.add(new Dog("老黄",47));
list.add(new Cat("招财猫",7));
for (Dog dog : list) {
System.out.println(dog.toString());
}
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Cat{
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
}
代码在第三行添加了泛型,然后在第7行list.add(Cat)时编译器就会发现错误,不能在Dog泛型的集合添加Cat类实例,可以约束数据,同时在遍历时第8行可以直接转换为Dog对象,不需要先转换Object,然后向下转型,提高效率。
泛型简介:
-
泛型又称参数化类型,是jdk5.0出现的新特性,解决数据类型的安全问题
-
在类声明或实例化对象时只要指定好需要的具体的类型即可,E在编译时就确定好,如果类型不相符合,编译器就会警告
-
java泛型可以保证如果程序在编译时没有发出警告,运行就不会产生ClassCastException(类转换异常)。同时,代码更加简洁,健壮
-
泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回类型,比如:
public static void main(String[] args) { Person<Integer> person = new Person<Integer>(44);//传入Integer类型代表泛型 System.out.println(person.getName());//结果为44 Person<String> jack = new Person<>("jack");//传入String类型代替泛型 System.out.println(jack.getName());//结果:jack } class Person<E>{ private E name;//E表示泛型,在实例化Person对象时,构造器中传入什么类型,E就是什么类型 public Person(E name) { this.name = name; } public E getName() { return name; } public void setName(E name) { this.name = name; } }
使用细节:
-
任意字母都可以表示泛型
-
泛型的实际类型在编译期间确定
-
使用泛型接口或泛型类时如果不指定泛型实际类型,则泛型为Object
-
使用泛型的数组,不能初始化
-
静态成员不能使用泛型
-
泛型类的类型,是在创建对象时确定的
-
泛型接口中,属性能使用泛型(因为属性都是静态的)
-
继承或实现泛型接口(类)时,需要确定泛型类型,不写默认Object
-
泛型不具备继承性
List<Object> list = new ArrayList<String>(); //会报错,虽然String是Object类的子类,但是泛型不具备继承性
-
List<?>表示任意的泛型类型都可以接受
-
List<? extends AA> 表示上限,可以接受AA或者AA的子类
-
List<? super AA> 表示下限,可以接受AA或者AA的父类