在学习Java泛型的过程中,我们常常看到这样泛型的使用, class Person<E extends Number>, 这个表示什么呢,这个其实就是java 泛型的upper bound(上限界定),它给我们带来了什么呢?实际上,它定义了以下3个内容:
- 限定了一组可用于实例化泛型参数的类型。
- 能够访问基类所定义的所有非private成员(方法以及属性)。
- 在编译成字节码时,用基类代替所有的占位符E。
先来看第一点,E extends Number表示在实例化这个类型参数的时候,只能使用Number的子类进行实例化。如:
Person p1= new Person<Long>();// ok
Person p2=new Person<String>();//wrong
因为String并不是Number的子类,所以在进行实例化E类型参数时,编译器会提示错误。
对于第二点,我们看个例子,首先定义一个父子关系,Animal和AnimalSub,并在Animal中分别定义public/protected/private方法两份,一份对应于static,另一份对应于非static
Animal Class:
public class Animal {
public static void staticPublicMethod() {
System.out.println("staticPublicMethod");
}
protected static void staticProtectedMethod() {
System.out.println("staticProtectedMethod");
}
private static void staticPrivateMethod() {
System.out.println("staticPrivateMethod");
}
public void publicMethod() {
System.out.println("publicMethod");
}
protected void protectedMethod() {
System.out.println("protectedMethod");
}
private void privateMethod() {
System.out.println("privateMethod");
}
}
AnimalSub class:
public class AnimalSub extends Animal {
}
然后我们来使用这个泛型的上限界定符,
public class Person <E extends Animal>{
private E e;
public Person(E animal)
{
e=animal;
}
public void invokeNumberMethod()
{
e.staticPublicMethod();
e.staticProtectedMethod();
e.publicMethod();
e.protectedMethod();
}
}
从Person类可以看出,除了Animal中的private的方法,我们都可以进行调用,属性成员类似。这里E代表Animal的子类或者Animal本身,与类的extends有些差别。
第三点是在编译器将java代码编译成字节码的时候,会使用上限界定的基类把占位符都替换掉,对于上面的Person类,编译后,实际上就是:
public class Person {
private Animal e;
public Person(Animal animal)
{
e=animal;
}
public void invokeNumberMethod()
{
e.staticPublicMethod();
e.staticProtectedMethod();
e.publicMethod();
e.protectedMethod();
}
}
可以看出,原先的占位符E都被Animal所代替了。