泛型的深入研究
一 泛型定义
允许在定义类、接口、方法时指定类型形参,这个类型形参在将在声明变量、创建对象、调用方法时时动态确定(即传入实际的类型参数,也可称为类型实参)。JDK1.5改写了集合框架中的全部接口和类,为这些接口、类增加了泛型支持,从而可以在声明集合变量、创建集合对象时传入类型实参。
二 泛型实质
允许在定义接口、类时声明类型形参,类型形参在整个接口,类体内可当成类型使用,几乎所有可使用普通类型的地方都可以使用这种类型形参。例如:使用List类型时,如果为E形参传入String类型的实参,则产生一个新的类型:List<String>类型,可以把List<String>想象成E被全部替换成String的特殊List子接口。
三 类的泛型声明
1 代码示例
public class Apple<T> { // 使用T类型形参定义实例变量 private T info; public Apple(){} // 下面方法中使用T类型形参来定义构造器 public Apple(T info) { this.info = info; } public void setInfo(T info) { this.info = info; } public T getInfo() { return this.info; } public static void main(String[] args) { // 由于传给T形参的是String,所以构造器参数只能是String Apple<String> a1 = new Apple<>("苹果"); System.out.println(a1.getInfo()); // 由于传给T形参的是Double,所以构造器参数只能是Double或double Apple<Double> a2 = new Apple<>(5.67); System.out.println(a2.getInfo()); } }
2 运行结果
苹果
5.67
3 代码分析
上面程序在定义了一个带泛型声明Apple<T>类,使用Apple<T>类就可为T类型形参传入实际类型,这样就可以生成Apple<String>、Apple<Double>形式的多个逻辑子类(物理上并不存在)。
四 泛型类派生子类
1 当从泛型类派生子类的时,不能再包括类型形参。
public class A extends Apple<T>{} 这种定义是错误的。
2 定义类、接口、方法时可以声明类型形参,但使用类型,接口,方法时应该为类型形参传入实际的类型。
public class A extends Apple<String>{} 这种定义是正确的。
3 调用方法时必须为所有的数据传入值,但使用类、接口时,也可以不为类型形参传入实际的类型参数。
public class A extends Apple{} 这种定义是正确的。
4 从泛型类派生子类举例——传入实际类型参数。
public class A1 extends Apple<String> { // 正确重写了父类的方法,返回值 // 与父类Apple<String>的返回值完全相同 public String getInfo() { return "子类" + super.getInfo(); } /* // 下面方法是错误的,重写父类方法时返回值类型不一致 public Object getInfo() { return "子类"; } */ }
5 从泛型类派生子类举例——不传入实际类型参数。
public class A2 extends Apple { // 重写父类的方法 public String getInfo() { // super.getInfo()方法返回值是Object类型, // 所以加toString()才返回String类型 return super.getInfo().toString(); } }
五 泛型的错误用法
1 不能在静态变量声明中使用类型形参。
static T info; //错误的
2 不能在静态方法中使用类型形参。
public static void bar(T msg) //错误的
3 instanceof运算符后不能使用泛型。
if(cs instanceof java.util.ArrayList<string>) //错误的
上一篇: ps字体描边在哪
下一篇: PHP如何防止远程提交