Java——泛型
Java—— 泛型
泛型的引入
对于不加泛型的集合
不能对加入到ArrayList中的数据类型进行约束
1
2
3
4
5ArrayList arraylist = new ArrayList();
arraylist.add(new Dog("dahuang",3));
arraylist.add(new Cat("tom",2));
//arraylist中可以添加任意类型
//如果要对arraylist进行遍历输出Dog信息时,Cat就会报错遍历时,需要进行类型转换(Object—>具体类),如果集合中数据量比较大,对效率有影响
1
2
3
4
5
6Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
Dog dog = (Dog) next; //向下转型
System.out.println(dog.getName() + dog.getAge());
}
加入泛型
1 | ArrayList <Dog> arraylist = new ArrayList<Dog>(); |
这样arraylist中只能存放Dog类数据
好处:编译时,检查添加元素的类型,提高了安全性,减少类型转换的次数,提高效率。
泛型概念及作用
泛型是一种在编译时提供更强类型检查的特性,它使得你可以在设计和使用类、接口和方法时参数化类型。
在类声明或实例化时,只要指定好需要的的具体类型即可。
泛型可以在类声明时通过一个标识表示类中某个属性的类型,或者某个方法返回值类型,或参数类型
1
2
3
4
5
6
7public class Box<T> {
// ...
}
public <T> T genericMethod(T parameter) {
// ...
}类型安全:泛型可以提供在编译时检查类型的机制,避免了运行时出现类型错误,提高安全性。
代码重用:泛型允许编写用于多种类型的的代码,而不必重复编写,提高代码重用性和可维护性。
集合框架:集合框架使用泛型,可以使得在集合中存储元素和检索元素更加安全,并且无需进行显示的类型转换。
泛型语法
泛型的声明:
interface 接口名
class 类名 <k,v…>{…}
泛型的实例化:
要在类名后面指定类型参数的值,如:
1 | List <String> strList = new ArrayList<>(); |
使用细节:
泛型K,T,V…只能是引用类型,不能是基本数据类型。
在给泛型指定具体类型后,可以传入该类型或者其子类型。
1
2
3
4
5Pig<A> aPig = new Pig<A>(new A());
Pig<A> aPig = new Pig<A>(new B());
class A{}
class B extends A{}
class Pig<T>{}泛型的使用形式:
1
2
3
4
5
6//通常将后面的省略
ArrayList<Integer> list1 = new ArrayList <>();
List<Integer> list2 = new ArrayList <>();
//不推荐
ArrayList<Integer> list3 = new ArrayList <Integer>();
List<Integer> list4 = new ArrayList <Integer>();如果没给泛型指定具体对象,则默认为Object
1
2
3ArrayList arraylist = new ArrayList();
//等价于
ArrayList <Object> arraylist = new ArrayList<>();
自定义泛型
自定义泛型类
基本语法:class 类名<T,R…>{…}
使用细节:
普通成员可以使用泛型(属性、方法)
使用泛型的数组不能对其进行初始化(数组需要根据数据类型分配空间)
静态方法中不能使用类的泛型(静态方法和属性,在类加载的适合就被加载和初始化,而不是在类实例化时)
泛型类的类型是在创建对象时确定的(因为创建对象时需要指定确定类型)
如果创建时没有指定类型,那就默认为Object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class CustomGenerics {
public static void main(String[] args) {
Student<Integer> student1 = new Student<>(001);
Student student2 = new Student(); //未指定类型则为Object
student2.setId(002);
student2.setId("002");
}
}
class Student<E>{ //泛型类
E id; //属性值泛型
public Student(){}
public Student(E id) { //方法泛型
this.id = id;
}
public void setId(E id) {
this.id = id;
}
}
自定义泛型接口
基本语法:interface 接口名 <T,R…>{…}
使用细节:
- 在接口中,静态成员变量也不能使用泛型
- 接口中的所有属性都默认为static,所以接口中属性不能用泛型
- 泛型接口的类型在继承接口或实现接口时确定
- 如果没有指定具体类型,则默认为Object
1 | interface AA<T,R>{ |
自定义泛型方法
基本语法:修饰符 <T,R…>返回类型 方法名(参数列表){…}
使用细节:
- 泛型方法可以定义在普通类中,也可以定义在泛型类中
- 当泛型方法被调用时,类型会确定
- public void eat (E e){},修饰符后没有<T,R…> eat方法不是泛型方法,只是使用了泛型
1 | public class CustomMethodGenerics { |
泛型的继承和通配符
泛型不具备继承性
1
2Object aa = new String("xx"); //true
List<Object> list = new ArrayList<String>(); //false- >:支持任意泛型类型
- extends A>:支持A类以及A类的子类,规定了泛型的上限(AA)
- super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限(AA)
1 | public class GenericExtends { |


