Java 泛型

泛型:宽泛的数据类型

一、泛型概念

Java在1.5之后加入了泛型的概念。泛型,即“参数化类型”。泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法

先举例:

ArrayList<String> list1=new ArrayList<String>();
//list1.add(520);//编译报错

ArrayList容器可以存放任何类型,但是list1指定了String类型,则需要以String型使用。为了解决类似这样的问题(在编译阶段就可以解决),泛型应运而生

        ArrayList<String> list1=new ArrayList<String>();
        ArrayList<Integer> list2=new ArrayList<Integer>();
        //list1.add("守林鸟");
        //list1.add(520);//编译报错
        Class class1=list1.getClass();
        Class class2=list2.getClass();
        if(class1==class2)
            System.out.println("泛型测试,类型相同");//表示这是同一类型的对象

对于编译器来说,list1和list2是同一类型的对象,因为编译之后采取了类似于去泛型化的措施,也就是泛型的类型擦除


二、为什么要设计泛型

在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况 ,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。 
泛型的好处:使用泛型,首先可以通过IDE进行代码类型初步检查,然后在编译阶段进行编译类型检查,以保证类型转换的安全性;并且所有的强制转换都是自动和隐式的,可以提高代码的重用率


三、泛型的基本使用(一般用大写字母T,S等,不支持基本类型)

  1. 泛型类:class 类名<泛型标识符T>{}
  2. 泛型属性:和泛型类一起使用
  3. 泛型方法:[作用域修饰符] <泛型类型标识T> [返回类型] 方法名称(参数列表){};用泛型标识符把原本的类型替代掉,在方法的返回值类型、传参类型里。不是泛型类也可以有泛型方法,泛型方法与泛型类没有必然的联系。
  4. 泛型接口:interface 接口名<泛型标识符>;实现接口的类也需要生命泛型。如果传入实参类型(即把T改成具体类如String),则实现接口里所有方法的过程中,都需要把T改成String。

例如:知道某个人的信息,有时候需要传入int型的生日,有时候需要传入String型的姓名,不用泛型需要写2个类,用不同类型标识属性,泛型可以实现代码复用

//测试泛型
public class TestF{

    public static void main(String[] args) {
        Person p1=new Person(19981102);
        Person p2=new Person("守林鸟");
        Person p3=new Person(520.1314);
        System.out.println(p1);
        System.out.println(p2);
        System.out.println(p3);
        p1.walk("博客园");
        p1.walk(10086);
        Man man=new Man();
        man.eat("鸭子");
        man.eat(1314);
        Super_Dog sDog=new Super_Dog();
        sDog.jiao(10022222);
        sDog.jiao("霸王别鸡");
    }
}

class Person<T>{
    private T message;
    public Person(T message) {
        this.message=message;
    }
    public String toString() {
        return "这个人的信息是"+this.message;
    }
    public <S> void walk(S type) {//这里的S和T不冲突,因为方法可以独立使用泛型
        System.out.println("这里调用了walk方法,type="+type);
    }
}

interface Human<S>{
    public S eat(S food); 
}

class Man<S> implements Human<S>{//实现类Man也需要声明泛型
    public S eat(S food) {
        System.out.println("food="+food);
        return food;
    }
}
class Super_Dog{
    public <P> void jiao(P p) {//类没有泛型,方法有泛型
        System.out.println("P="+p);
    }
}

输出:

这个人的信息是19981102
这个人的信息是守林鸟
这个人的信息是520.1314
这里调用了walk方法,type=博客园
这里调用了walk方法,type=10086
food=鸭子
food=1314
P=10022222
P=霸王别鸡

还有通配符和边界的知识点,翻了很多博客都看不懂,先放着吧,感觉短时间内也用不上。。。

原文地址:https://www.cnblogs.com/shoulinniao/p/11686553.html