java泛型示例

double

记录一下

首先我们要知道,java的泛型是编译期间的而非运行期间。

泛型类命名规范

泛型并没有强制的命名规范,但是为了便于代码阅读,也都形成了一些约定俗成的命名规范。

  • T: 通用泛型类型,Type (java类型)
  • S: 通用泛型类型,如果需要使用多个泛型类型,可以将S作为第二个泛型类型
  • U: 通用泛型类型,如果需要使用多个泛型类型,可以将U作为第三个泛型类型
  • V: 通用泛型类型,如果需要使用多个泛型类型,可以将V作为第四个泛型类型
  • E: 集合元素泛型,Element的缩写(因为集合中存放的是元素)
  • K: 映射-键(Key) 泛型类型,主要用于定义映射泛型类型
  • V: 映射-值(value) 泛型类型,主要用于定义映射泛型类型
  • N: 数值 泛型类型,主用用于定义数值类型的泛型类型
  • ?: 表示不确定的java类型

泛型类

泛型类的基本定义,在没有任何类型参数的【泛型类、接口】也可称为原生类型,即原生类型的概念只针对泛型而言。

public class Box<T> { private T name; private T add; public T getName() { return name; } public void setName(T name) { this.name = name; } public T getAdd() { return add; } public void setAdd(T add) { this.add = add; } }

在创建参数化类型的 Box<T>,需要传入实际类型参数,如:

Box strBox = new Box<>();

但是,如果不指定类型参数,则会创建一个原生类型 Box:

Box rawBox = new Box();

Box 是泛型Box<T>的原生类型。

泛型方法

[权限修饰符] <T1,T2,…,Tn> 返回类型 methods(…) {}

PS: <T1,T2,…,Tn> 对应着泛型方法的参数类型列表,它置于方法返回类型之前,

public class MyThree { /** * 定义一个泛型方法 * @param <T> * @return */ public <T> T sayName(T t) { return t; } }

有界类型参数

有时候,我们需要可以限制类型参数的类型,如: 对数字操作的方法只想接收 Number 或其子类的对象,这种情况下,有界类型参数就发挥作用了。
声明有界类型参数,需要指定类型参数的名称,然后是 extends 关键字,后接其上线。

<T extends SomeType >

示例

public class Genericity<T> { private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } public <U extends Number> void inspect(U u) { System.out.println("T:" + t.getClass().getName()); System.out.println("U:" + u.getClass().getName()); } public static void main(String[] args) { Genericity<Integer> integerGenericity = new Genericity<>(); integerGenericity.setT(new Integer(10)); // 传入 String 类型会出错 integerGenericity.inspect(23); } }

这里我指定接收 Number 及其子类型对象,当我们想 inspect 方法传递一个 String 对象时,会发生错误。

多个边界

实际上类型参数是可以有多个边界的,在多边界时,类型变量是指定的所有类型的子类型

<T extends A1 & A2 & A3>

通配符 “?”

用来表示不确定的java类型,如下:

// 这个未知的类型实际上是 Collection 的一个子类,Collection 是这个通配符的上限 class Test <T extends Collection> {} // 如果每一个针对每一种都要写出具体的子类型,那也太麻烦了,这时候就可以用 "?" (未知通配符泛型),这个类型只要实现 Collection 接口即可。 class Test <? extends Collection> {}

java 泛型和C++模板区别

  • C++模板可以使用int等基本数据类型,java则不行,必须转而使用Integer。
  • 在Java中,可以将模板的类型参数限定为某个特定类型,如: 使用泛型实现 CarDeck,并规定类型参数必须扩展自 CarDeck。
  • 在 C++ 中,类型参数可以实例化,但 Java 不支持。
  • 在Java中,类型参数(即MyClass中的Foo)不能用于静态方法和变量,因为它们会被MyClass和MyClass所共享,在C++中,这些类型都是不同的,因此类型参数可以用于静态方法和静态变量。
  • 在Java中,不管类型参数是什么,MyClass的所有实例都是同一类型。类型参数会在运行时被抹去,在C++中参数类型不同,实例类型也不同。

参考文章

Java泛型详解
JAVA 泛型中的通配符 T,E,K,V,?
Java泛型系列
Java 之路 (十五) – 泛型上