Featured image of post 简单的Java泛型学习

简单的Java泛型学习

Java泛型的学习和理解,以及为什么要用泛型

泛型

泛型特性

百度得如下解释:

1
泛型是程序设计语言的一种特性,允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。 

举个栗子

1
2
3
4
5
6
7
List Li = new ArrayList();
Li.add("sdn");
Li.add(90);

for (Object se :Li){
	System.out.println(se);   
}
1
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

典型的类型转换异常,Integer不能被转换成String

正确的写法如下:

1
List<String> Li = new ArrayList<String>();

泛型的使用

泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法

泛型类

泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map。

一个最普通的泛型类:

1
2
3
4
5
6
7
8
9
public class examples<Human>{ 
    private Human key;
    public examples(Human key) { 
        this.key = key;
    }
    public Human getKey(){ 
        return key;
    }
}

注意事项

泛型的类型参数只能是类型,不能是简单类型。

不能对确切的泛型类型使用instanceOf操作,编译时会出错。

泛型接口

泛型接口与泛型类的定义及使用基本相同

1
2
3
public interface killSky<Gun> {
    public Gun next();
}

实现泛型接口的类也必须要保证该类的泛型和接口保持一致

1
2
3
4
5
6
class Fun<Gun> implements killSky<Gun>{
    @Override
    public Gun next() {
        return null ;
    }
}

泛型通配符

在写代码时可能会遇到下面的情况,通配符就会统统匹配

1
2
3
4
public static void printCollection(Collection<?> coll) {
		for (Object obj:coll){
			System.out.println(obj);
		}

泛型方法

泛型类,是在实例化类的时候指明泛型的具体类型,那么泛型方法,就是在调用方法的时候指明泛型的具体类型 。

静态方法与泛型

静态方法有一种情况需要注意一下,那就是在类中的静态方法使用泛型:静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。

即:如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法 。

1
2
3
4
5
6
7
public class StaticGenerator<T> {
    ....
    ....
    public static <T> void show(T t){

    }
}

泛型上下边界

在使用泛型的时候,我们还可以为传入的泛型类型实参进行上下边界的限制,如:类型实参只准传入某种类型的父类或某种类型的子类。

为泛型添加上边界,即传入的类型实参必须是指定类型的子类型

1
2
3
4
5
6
public void showKeyValue1(Generic<? extends Number> obj){
    System.out.println(obj)
} 
public void showKeyValue1(Generic<? super Number> obj) {
    System.out.println(obj)
}
1
2
3
4
5
6
7
//在泛型方法中添加上下边界限制的时候,必须在权限声明与返回值之间的<T>上添加上下边界,即在泛型声明的时候添加
//public <T> T showKeyName(Generic<T extends Number> container),编译器会报错:"Unexpected bound"
public <T extends Number> T showKeyName(Generic<T> container){
    System.out.println("container key :" + container.getKey());
    T test = container.getKey();
    return test;
}

看到了很多文章中都会提起泛型数组,经过查看 sun 的说明文档,在 Java 中是”不能创建一个确切的泛型类型的数组”的。

也就是说下面的这个例子是不可以的:

1
List<String>[] ls = new ArrayList<String>[10];  

而使用通配符创建泛型数组是可以的,如下面这个例子:

1
List<?>[] ls = new ArrayList<?>[10]; 

这样也是可以的:

1
List<String>[] ls = new ArrayList[10];

下面使用Sun的一篇文档的一个例子来说明这个问题:

Licensed under CC BY-NC-SA 4.0