jdk1.5之后的新特性, jdk1.8之后, 等号右边的泛型不用写
可以在创建对象的时候, 明确类型, 常见在容器中使用
interface MyInterface<T> {
}
class test1 implements MyInterface<String> {
}
class test<T> implements MyInterface<T> {}
class MyMethod <T> {
public void show(T t) {
System.out.println(t);
}
}
//泛型方法, 不一定在泛型类中声明, 在不是泛型的类中, 也可以使用
public <Q> void method(Q para) {
System.out.println(para);
}
// 调用的时候, 直接传参就行, 自动确认类型
泛型的界限是很有用的
假如有一个类我们希望他的泛型类型是Number类的子类, 比如是Integer或是Long, 但是泛型本身是不支持不同类型的泛型的, 于是有了泛型界定
我们使用 来表示一个泛型的上界. 也就是说这个T类型, 必须是Number或Number的子类, 可以这样理解, T是继承自Number的类, T也可用通配符?代替
public statci <T extends Number> T add(T a, T b) {
return a + b;
}
// 如上边那个例子, 是一个通用方法, 界定了泛型必须是Number的子类
//同样, 我们使用 来界定下界. 所有的T类型, 必须是Integer的父类或Integer类
在源码中, 我们经常看到这样的代码
<T extends Comparable<T>>
有的同学可能已经蒙了. 其实这也是一个泛型的界定例子. 虽然他继承的类也是个泛型类, 多了个泛型T
上边这个例子你可以这样理解: T是一个实现了Comparable接口的类. 不实现这个接口就不能作为这个泛型
当子类继承泛型父类(或者是泛型接口)时候, 有几种情况.
父类将泛型指定
这种情况时, 子类并不是一个泛型类, 就是个正常的类
//存在父类
class Father<T> {
T name;
}
class Son extends Father<String> {}
//此时, 子类继承过后的代码应该是
class Son {
String name;
}
子类也是个泛型类
这个时候, 子类的泛型T和父类的泛型T是一个泛型, 创建子类的时候,需要给子类泛型确定的类型, 同时, 会把父类的泛型也指定了.
class Son<T> extends Father<T> {
public T print(T a) {
System.out.println(a);
return a;
}
}
//此时, 子类继承过后的代码应该是
class Son {
T name;
public T print(T a) {
System.out.println(a);
return a;
}
}
子类拥有其他泛型, 父类指定类型
class Son<T> extends Father<String> {
public T print(T a) {
System.out.println(a);
return a;
}
}
//此时, 子类继承过后的代码应该是这样的, 注意, 继承父类的泛型, 被指定了. 但是, 子类拥有自己的泛型T, 并没有被指定, 所以继承过好如下
class Son<T> extends Father<String> {
String name;
public T print(T a) {
System.out.println(a);
return a;
}
}
子类拥有多种泛型
class Son<T, E> extends Father<T> {
public E print(E e) {
System.out.println(a);
return a;
}
}
// 这个时候, 子类的T和父类的T是一个泛型, 继承过后是这样的
class Son <T, E> {
T name;
public E print(E e) {
System.out.println(a);
return a;
}
}
所以对于泛型的继承来讲, 不管子类是不是泛型类, 有多少个泛型类型. 所继承或实现的父类或接口, 必须被指定.
有时候在创建子类对象的时候指定, 有时候在写子类的时候实现,但是,规则就是父类的类型一定要被指定, 不然编译的时候就会报错.