Java--泛型的初步认识

什么是泛型?
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
1)泛型让编程人员能够使用类型抽象,通常用于集合里面。
2)泛型只在编译阶段有效

泛型类:
一般用于封装非特定数据类型的操作,操作执行的大体相同,与所存储的数据类型无关。
泛型类的声明与一般类的声明语法一致,但需要在生命的泛型接口名称后使用”<>”,制定类型参数。

示例:
class TypeTest<T> {
private T number; // 定义泛型成员变量
public TypeTest(T number) {
this.number = number;
}
public T getNum() {
return number;
}
public void setNum(T number) {
this.number = number;
}
public void showType() {
System.out.println("T 的实际类型是: " + number.getClass().getName());
}
}

泛型的意义:
a.可以对类型进行自动检查 注意:不是替换 仅仅是用来进行类型安全检查!!!!!!
b.自动对类型进行类型转换

泛型注意之处:
(1)不能直接 new 泛型数组
(2)不能定义泛型对象的数组
(3)不能产生泛型类型对象
(4)在 static 方法中,是不能用泛型类型参数的。因为 static 方法是不依赖对象存在的,所以无法推知static 泛型参数类型。
(5)泛型参数类型不能是基本数据类型引用数据类型

泛型实现原理:
(1)Java范型时编译时技术,在运行时不包含范型信息,仅仅Class的实例中包含了类型参数的定义信息。
(2)一个泛型类被其所有调用共享
(3)转型和instanceof
泛型类被所有其实例(instances)共享的另一个暗示是检查一个实例是不是一个特定类型的泛型类是没有意义的。

   Collection cs = new ArrayList<String>();
   if (cs instanceof Collection<String>) { ...} // 非法

类似的,如下的类型转换

Collection<String> cstr = (Collection<String>) cs;

得到一个unchecked warning,因为运行时环境不会为你作这样的检查。

边界符
现在我们要实现这样一个功能,查找一个泛型数组中大于某个特定元素的个数,我们可以这样实现:

public static <T> int countGreaterThan(T[] anArray, T elem) {
    int count = 0;
    for (T e : anArray)
        if (e > elem)  // compiler error
            ++count;
    return count;
}

但是这样很明显是错误的,因为除了short, int, double, long, float, byte, char等原始类型,其他的类并不一定能使用操作符>,所以编译器报错,那怎么解决这个问题呢?答案是使用边界符。

public interface Comparable<T> {
    public int compareTo(T o);
}

做一个类似于下面这样的声明,这样就等于告诉编译器类型参数T代表的都是实现了Comparable接口的类,这样等于告诉编译器它们都至少实现了compareTo方法。

public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) {
    int count = 0;
    for (T e : anArray)
        if (e.compareTo(elem) > 0)
            ++count;
    return count;
}

(泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。)

泛型的好处
(1)类型安全。
通过知道使用泛型定义的变量的类型限制,编译器可以更有效地提高Java程序的类型安全。
(2)消除强制类型转换。
消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。所有的强制转换都是自动和隐式的。
(3)提高性能。

示例1

  1.Lits list1 = new ArrayList();  
    2.list1.add("CSDN_SEU_Cavin ");  
    3.String str1 = (String)list1.get(0); 

示例2

1.List<String> list2 = new ArrayList<String>();  
2.list2.add("CSDN_SEU_Cavin ");  
3.String str2 = list2.get(0);  

对于上面的两段程序,由于泛型所有工作都在编译器中完成,javac编译出来的字节码是一样的(只是更能确保类型安全),那么何谈性能提升呢?是因为在泛型的实现中,编译器将强制类型转换插入生成的字节码中,但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来了可能。

猜你喜欢

转载自blog.csdn.net/Snowing1234_5/article/details/84842920