泛型工作原理
Java中的泛型都是编译器层面来完成的,在生成的Java字节码中是不包含任何泛型中的类型信息的。使用泛型时加上的类型参数,会在编译时被编译器去掉。也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。
泛型类
定义的泛型类,就一定要传入泛型类型实参吗?并不是这样,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。
package generic;
public class MyClass<T,E> {
private T object;
public T getObject() {
return object;
}
public void setObject(T object) {
this.object = object;
}
public static void main(String[] args) {
MyClass<String,Integer> myclass = new MyClass<String,Integer>();
myclass.setObject("费哥6666");
System.out.println(myclass.getObject());
}
}
泛型接口
package MyGenerator;
public interface MyGeneric<T> {
T getObejct();
void setObject(T object);
}
当实现泛型接口的类,未传入泛型实参时:需要在声明类的时候,需将泛型的声明也一起加到类中。
package MyGenerator;
public class ChildOne<T> implements MyGeneric<T>{
@Override
public T getObejct() {
return null;
}
@Override
public void setObject(T object) {
System.out.println(6666);
}
}
当实现泛型接口的类,传入泛型实参时:则所有使用泛型的地方都要替换成传入的实参类型。
package MyGenerator;
public class ChildTwo implements MyGeneric<String>{
@Override
public String getObejct() {
return null;
}
@Override
public void setObject(String object) {
}
}
泛型通配符"?"
package MyGenerator;
public class ChildTwo<T>{
public String name;
public ChildTwo(String name) {
this.name = name;
}
}
public class Test {
public static String getObejct(ChildTwo<?> child) {
System.out.println(child.name);
return null;
}
public static void main(String[] args) {
ChildTwo<String> one = new ChildTwo<String>("fei");
ChildTwo<Integer> two = new ChildTwo<Integer>("666");
getObejct(one);
getObejct(two);
}
}
结果:
fei
666
泛型方法
泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 ,泛型方法能使方法独立于类而产生变化。
public <E> void say(ChildTwo<E> child) {
String name = child.name;
System.out.println(name);
}
泛型方法的上下边界
在泛型方法中添加上下边界限制的时候,必须在权限声明与返回值之间的
public <T extends Number> void showKeyName(Generic<T> container){
System.out.println("container key :" + container.getKey());
}
public <T super Number> void showKeyName(Generic<T> container){
System.out.println("container key :" + container.getKey());
}