Java 泛型generic

李疏珂
2023-12-01

语法

import java.util.ArrayList;

public class Generic_01 {
    public static void main(String[] args) {
        //当如下写时,arraylist中存放的元素只能是Dog类型
        ArrayList<Dog> arrayList = new ArrayList<Dog>();
        arrayList.add(new Dog("Mary",22));
        arrayList.add(new Dog("Sam",18));
        arrayList.add(new Dog("Jone",15));
        //当遍历的时候,可以直接取出Dog类型,而不是Object类型。少了向下转型的转换。
        for (Dog dog:arrayList){
            System.out.println(dog.getAge()+" "+dog.getName());
        }
    }
}

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 int getAge() {
        return age;
    }
}

class Cat{
    private String name;
    private int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
22 Mary
18 Sam
15 Jone

Process finished with exit code 0

泛型的好处是
1、编译时,检查添加元素的类型,提高了安全性。
2、减少了类型转换的次数,提高效率。

泛型的作用可以在类声明时通过一个标识表示类中某个属性的类型,或者某个方法返回值的类型,或者是参数类型。

public class Generic_02 {
    public static void main(String[] args) {
        Person<String> stringPerson = new Person<String>("名字");

    }
}
class Person<E>{
    //用E表示s的数据类型,该数据类型是在创建person对象的时候指定的。在编译期间确定的。
    E s;

    public Person(E s) {
        this.s = s;
    }

    public E function(){
        return s;
    }
}

注意E不代表值,而是表示类型。任意字母都是可以的。像T、E、G。注意放的时候只能是引用数据类型,放入基本数据类型会报错。

案例:创建3个学生对象,放入到HashSet中学生对象。放入到HashMap中,要求Key是String name,Value是学生对象。

import java.util.*;

public class Generic_03 {
    public static void main(String[] args) {
        HashSet<Student> hashSet = new HashSet<Student>();
        hashSet.add(new Student("Mary",18));
        hashSet.add(new Student("Sam",22));
        hashSet.add(new Student("Tom",25));
        for (Student student:hashSet){
            System.out.println(student.getAge()+" "+student.getName());
        }

        HashMap<String,Student> hashMap = new HashMap<String,Student>();
        hashMap.put("Tom",new Student("Tom",22));
        hashMap.put("Tony",new Student("Tom",18));
        hashMap.put("Amy",new Student("Amy",25));
        Set<Map.Entry<String,Student>> entries = hashMap.entrySet();
        Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Student> next =  iterator.next();
            System.out.println(next.getKey()+" "+next.getValue());
        }

    }
}

class Student{
    public String name;
    public int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
25 Tom
22 Sam
18 Mary
Tony Student@1540e19d
Tom Student@677327b6
Amy Student@14ae5a5

Process finished with exit code 0
public class Generic_04 {
    public static void main(String[] args) {
        Pig<A> aPig = new Pig<A>(new A());
        Pig<A> aPig1 = new Pig<A>(new B());//由于B类继承了A类,所以在这里是B类是没有问题的。
    }
}
class A{}
class B extends A{}

class Pig<E>{
    E s;

    public Pig(E s) {
        this.s = s;
    }
}

在实际开发中,往往可以简写,也是推荐的写法,就是等号右边尖括号中可以不写内容。如果没有指定类型,默认的泛型是Object。

自定义泛型

自定义泛型就是自己写的一个类或者接口,在后面加上泛型。
注意:
1、属性和方法可以使用泛型
2、使用泛型的数组是不能初始化的。
3、静态属性、静态方法中不能使用类的泛型。
4、泛型类的类型,是在创建对象的时候确定的。
5、如果创建对象时,没有指定类型,则默认是Object。

泛型类

public class Generic_05 {
    public static void main(String[] args) {

    }
}
//自定义泛型
class Employee<T,G,E>{
    public String name;
    T t;
    G g;
    E e;

    public Employee(String name, T t, G g, E e) {
        this.name = name;
        this.t = t;
        this.g = g;
        this.e = e;
    }
}

泛型接口

语法:
interface 接口名<T、R>{

}

注意:
1、在接口中,静态成员也不能使用泛型。
2、泛型接口的类型,在继承接口或者实现接口时确定。
3、没有指定类型,则默认是Object类型。

泛型方法

基本语法
修饰符 <T、R> 返回类型 方法名(参数列表){

}

泛型方法可以定义在普通类中,也可以定义在泛型类中。
在泛型方法被调用的时候,确定泛型类型。

public class Generic_07 {
    public static void main(String[] args) {
        Car car = new Car();
        //当调用方法时,传入参数,编译器就会确定类型。
        car.m1("名字",100);
        car.m1(100,"String");
    }
}

class Car{
    public<T,E> void m1(T t,E e){
        System.out.println(t.getClass());
        System.out.println(e.getClass());
    }
}

注意区分泛型方法方法使用了泛型

泛型继承和通配符

泛型不具备继承性。

<?> 支持任意泛型类型 <? extends A> 支持A类以及A类的子类,规定了泛型的上限。 <? super A>支持A类以及A类的父类,不限于直接父类,规定了泛型的下限。
 类似资料: