泛型的核心概念:告诉编译器想使用什么类型,然后它帮你处理一切细节
泛型类定义
class Holder<T>{
private T a;
public Holder(T a){
this.a = a;
}
public T getA() {
return a;
}
public void setA(T a) {
this.a = a;
}
}
class Holder<T>中的T就是类型参数,类型参数的命名规则跟变量的命名规则一样,但常用T、E、K、V命名,一般使用一个大写字母。
Holder<String> strHolder = new Holder<String>("str");
//Holder<Integer> intHolder = new Holder<Integer>("str");
//参数类型定义为Integer,传入string的话编译器就会拒绝
String str = strHolder.getA();//编译会自动转换成String,不需要做类型转换
泛型的好处显而易见,Holder可以处理所有类型,编译器帮助类型判断与类型转换,Java1.5后集合类使用泛型实现,提高了可读性和安全性。
泛型类继承
class Holder2 extends Holder<String>{
public Holder2(String a) {
super(a);
}
@Override
public void setA(String a) {
super.setA(a);
}
@Override
public String getA() {
return super.getA();
}
}
继承泛型类的时候需要指明继承类的类型参数,如果不声明的话,编译器会把它当成Object
class Holder3 extends Holder{
public Holder3(Object a) {
super(a);
}
@Override
public void setA(Object a) {
super.setA(a);
}
@Override
public Object getA() {
return super.getA();
}
}
这样的话Holder2和Holder3就不是泛型类了,也可以这样继承
class Holder4<T> extends Holder<T>{
public Holder4(T a) {
super(a);
}
@Override
public void setA(T a) {
super.setA(a);
}
@Override
public T getA() {
return super.getA();
}
}
Holder4依然是泛型类,父类的参数类型也是由Holder4在使用时定义
class Holder5<T,E,K,V> extends Holder<T>{
private E e;
public Holder5(T a) {
super(a);
}
}
泛型类是可以定义多个类型参数的
泛型接口定义
泛型接口的定义跟泛型类的定义差不多
interface Holder<T>{
void setElement(T t);
T getElement();
}
class HolderImpl implements Holder<String>{
@Override
public void setElement(String s) {
}
@Override
public String getElement() {
return null;
}
}
泛型方法定义
class Holder{
public <T> void f(T t){
System.out.println(t.getClass().getName());
}
}
Holder holder = new Holder();
holder.f(33);
holder.f("1231");
在返回值前面声明类型参数,使用的时候不用指定具体类型,编译器会做类型推断
目录
学会Java泛型系列(零):简介及目录
学会Java泛型系列(一):Java泛型
学会Java泛型系列(二):泛型定义与使用
学会Java泛型系列(三):泛型原理-擦除
学会Java泛型系列(四):擦除带来的问题以及解决办法
学会Java泛型系列(五):限定符
学会Java泛型系列(六):总结
学会Java泛型系列(七):常用案例