【JAVA学习】Java泛型(一)

    在工作中经常会使用到泛型,所以整理一些泛型相关的资料,一起理解,学习一下。

1.泛型是什么,解决了什么问题。

    泛型又叫参数化类型,就是将类型像参数一样传递,可以在类,接口,方法中使用。在调用时,传递具体的类型。它可以提高代码的可重用性,让我们可以方便的实现一些通用算法,还可以提供更强大的类型检查,在编译阶段就可以发现代码的安全性错误,相比运行时才发现错误,可以让我们更好的定位,修复错误。

2.泛型的三种使用方式

2.1 泛型类

泛型类通过在类名后加上一对尖括号 <T,T...>来定义,下面看代码:

  class ClassName<T>{/* ... */}

    括号中的内容,就是指定的类型参数。通常类型参数名称是单个大写字母。最常用的类型参数名称是:

  • E - 元素(由 Java 集合框架广泛使用)
  • K - Key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types

下面是一个最简单的泛型类:

public class Generics<T> {

    private T t; /* 泛型成员变量 */

    /* 泛型成员方法(无返回值) */
    public void set(T t) {
        this.t = t;
    }

    /* 泛型成员方法(有返回值) */
    public T get() {
        return t;
    }
}

上面Generics类中的<T>就是要传入的参数,下面看看泛型类是怎样调用/实例化的。

Generics<Integer> gInt = new Generics<Integer>();

上面例子中的Integer类型,就像参数一样传递给了Generics类。

需要注意的是,在泛型类中,不可以声明类型为,类型参数的静态字段:
public class Generics<T> {
    private static T t; /* error 编译时会报错*/
}

如果Java允许这样声明,那么我们看看下面的例子:

Generics<Integer> gInt = new Generics<Integer>();
Generics<String> gString = new Generics<String>();
Generics<Double> gDouble= new Generics<Double>();

因为静态字段会被以上三个对象共享,所以它的类型是什么呢?因此,不可以声明类型为,类型参数的静态字段。

2.1.1 原生类型(raw type)

原生类型就是一个泛型类在我们在使用时,没有传递类型参数。下面看一个例子:

public class Generics<T> {
    private T t; /* 泛型成员变量 */
}

我们正常实例化这个类时会传递类型参数:

Generics<Integer> gInt = new Generics<Integer>();

下面是原生类型,调用时不传递参数类型:

Generics g = new Generics();

    原生类型是Java在推出了泛型后,为了兼容过去的代码而产生的。所以Java为了向后兼容,允许将参数化类型分配给它的原生类型:

Generics<Integer> gInt = new Generics<Integer>(); /* 参数化类型*/
Generics g = gInt; /* 原生类型*/

如果将原生类型分配给参数化类型会收到一个警告:

Generics g = new Generics(); /* 原生类型*/
Generics<Integer> gInt = g; /* 警告:未经检查的类型转换 */

如果使用原生类型去调用对应泛型中的方法只会得到一个警告:

Generics<Integer> gInt = new Generics<Integer>();
Generics g = gInt;
g.set("a");

这种调用方式会绕过泛型的类型检查,代码的安全性错误会在运行时才能发现。所以尽量不要使用原生类型。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。