天天看点

Java基础学习笔记 - 泛型

    泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

    Java语言引入泛型的好处是安全简单。

    在Java SE 1.5之前,没有泛型的情况下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显示的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器不提示错误,在运行的时候才会出现异常,这是一个安全隐患。隐患示例如下:

import java.util.*;

public class Test25_1 {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();

        // 创建一只狗,并存放到集合中
        Dog dog1 = new Dog("旺财", 2);
        al.add(dog1);

        //从集合中取出
        Dog temp1 = (Dog)al.get(0);        //此处一定需要作强制转换,否则编译报错
        Cat temp2 = (Cat)al.get(0);        //此处编译不会报错,但是运行时会报类型转换错误
    }
}

class Dog
{
    private String name;
    private int age;

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

class Cat
{
    private String name;
    private String color;

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

    上述代码运行,会报类型转换错误:

Java基础学习笔记 - 泛型

    泛型的好处是在编译的时候检测类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。如下,改成下面的代码,便不需要作强制转换。

public static void main(String[] args) {
        ArrayList<Dog> al = new ArrayList<Dog>();   //使用泛型

        // 创建一只狗,并存放到集合中
        Dog dog1 = new Dog("旺财", 2);
        al.add(dog1);

        //从集合中取出
        Dog temp1 = al.get(0);         //无需强制转换
        Cat temp2 = al.get(0);         //编译报错
    }
           

    通过泛型反射机制,可以获得类的很多信息,比如类的名称、类的函数名称、函数的返回类型等。

import java.util.*;
import java.lang.reflect.*;

public class Test25_1 {
    public static void main(String[] args) {
        Gen<Integer> gen1 = new Gen<Integer>(1);
        gen1.showTypeName();

        Gen<String> gen2 = new Gen<String>("apple");
        gen2.showTypeName();

        Gen<Bird> gen3 = new Gen<Bird>(new Bird());
        gen3.showTypeName();
        gen3.showMethodName();
    }
}

//定义一个泛型类
class Gen<T>
{
    private T o;

    // 构造函数
    public Gen(T t)
    {
        o = t;
    }

    // 通过反射机制,得到T类型的名称
    public void showTypeName()
    {
        System.out.println("类型是:"+o.getClass().getName());
    }

    // 通过反射机制,得到T类型的成员函数名称
    public void showMethodName()
    {
        Method[] m = o.getClass().getDeclaredMethods();
        for (int i = 0; i<m.length; i++)
        {
            System.out.println("函数名是:"+m[i].getName());
        }
    }
}

class Bird{
    public void test1()
    {
        System.out.println("Bird class");
    }

    public void count(int a, int b)
    {
        System.out.println(a+b);
    }
}
           

    运行结果:

Java基础学习笔记 - 泛型