泛型入门
public class Generic_ {
public static void main(String[] args) {
// 创建ArrayList
ArrayList arrayList = new ArrayList();
// 添加对象
arrayList.add(new Dog("大黄", 3));
arrayList.add(new Dog("小黄", 1));
arrayList.add(new Dog("旺财", 2));
// 遍历
for (Object o : arrayList) {
// 先向下转型,再输出
Dog dog = (Dog)o;
System.out.println(dog.getName() + "-" + dog.getAge());
}
// 传统方法,不能对加入到集合的数据类型进行约束
// 集合中可以加入Dog类,也可以加入Cat类等,这样在遍历时就产生的问题(需要先将对象向下转型为对应的类)
// 遍历的时候需要进行类型转换,数据量较大的时候,对效率有影响。
// 加入泛型,再创建集合
ArrayList<Dog> dogs = new ArrayList<>();
// 只能添加Dog类,添加其他类时会报错
dogs.add(new Dog("大黄", 3));
dogs.add(new Dog("小黄", 1));
dogs.add(new Dog("旺财", 2));
// 遍历
for (Dog dog : dogs) {
// 不需要向下转型了
System.out.println(dog.getName() + "-" + dog.getAge());
}
// 区别:
// 不使用泛型: Dog-加入 --> Object-取出 --> Dog
// 放入到ArrayList会先转为Object,再取出时,还需要转换为Dog
// 使用泛型: Dog --> Dog --> Dog; 放入取出不需要转换类型,提高效率。
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
泛型细节
1. <E> <T>,,,,,,,,,E或T只能是引用类型,不能是基本类型。例如,Integer可以,int不可以
2. 在指定泛型具体类型后,可以传入该类型或其子类型。
3. HashSet<Student> students = new HashSet<Student>(); 可简写为
HashSet<Student> students = new HashSet<>();
4. 若不指定泛型,则默认是Object类泛型。
自定义泛型类
自定义泛型接口
public class CustomGeneric {
public static void main(String[] args) {
Pig<String, Integer, Double> stringIntegerDoublePig = new Pig<String, Integer, Double>("qing", 12, 23.2);
}
}
// 自定义泛型类
// 普通成员可以使用到泛型
// 使用泛型的数组,不能初始化
// 静态方法不能使用类的泛型
// 泛型类的类型,实在创建对象时确定的(因为创建对象时,需要指定确定类型)
// 如果在创建对象时,没有指定泛型,则默认为Object
class Pig<T, R, M>{
T t; //属性使用到泛型
R r;
M m;
public Pig(T t, R r, M m) { // 构造器使用到泛型
this.t = t;
this.r = r;
this.m = m;
}
public T getT() {// 返回类型使用到泛型
return t;
}
public void setT(T t) {// 方法使用到泛型
this.t = t;
}
public R getR() {
return r;
}
public void setR(R r) {
this.r = r;
}
public M getM() {
return m;
}
public void setM(M m) {
this.m = m;
}
}
interface A<T, R>{
// 自定义泛型接口
// 1. 接口中,静态成员不能使用泛型
// 2. 泛型接口的类型,在继承接口或实现接口时确定
// 3. 没有指定类型,默认为Object
//T t; //错误,因为接口中的属性默认修饰符时 public final static, (方法默认修饰符是 public abstract)
}
自定义泛型方法
基本语法:
修饰符<T,R...> 返回类型 方法名(参数列表)
注意细节:
1. 泛型方法可以定义在普通类中,也可以定义在泛型类中
2. 当泛型方法被调用时,类型会确定
3. public void eat(E e){ } 修饰符后面没有<T,R...>, eat方法不是泛型方法,而是使用了泛型
public class CustomGenericMethod {
public static void main(String[] args) {
Car car = new Car();
car.fly("wxl", 123);// 当调用方法,传递参数,编译器会自动确定类型
Phone<String> stringPhone = new Phone<>();
stringPhone.call(123, "xiaomi");
}
}
class Car{// 普通类
public void run(){// 普通方法
}
public <T,R> void fly(T t, R r){ //泛型方法
}
}
class Phone<E>{// 泛型类
public <T> void call(T t, E e){// 泛型方法
}
}
泛型的继承与通配符
public class GenericExtend {
public static void main(String[] args) {
// List<Object> strings = new ArrayList<String>(); // 错误,泛型不具备继承性
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<AA> list3 = new ArrayList<>();
List<BB> list4 = new ArrayList<>();
List<CC> list5 = new ArrayList<>();
printCollection1(list1);
printCollection1(list2);
printCollection1(list3);
printCollection1(list4);
printCollection1(list5);
// 说明List<?> 表示任意的泛型都能接受
// printCollection2(list1); // 错误
// printCollection2(list2); // 错误
printCollection2(list3);
printCollection2(list4);
printCollection2(list5);
// 说明List<? extends AA> 只接受AA 及AA的子类
printCollection3(list1);
// printCollection3(list2); // 错误
printCollection3(list3);
// printCollection3(list4); // 错误
// printCollection3(list5); // 错误
// 说明List<? super AA> 只接受AA 及AA的父类
}
public static void printCollection1(List<?> c){
for (Object object : c) {
}
}
public static void printCollection2(List<? extends AA> c){
}
public static void printCollection3(List<? super AA> c){
}
}
class AA{
}
class BB extends AA{}
class CC extends BB{}