1.0.0 Summary
Tittle:【Java】-NO.16.EBook.4.Java.1.009-【疯狂Java讲义第3版 李刚】- 泛型
Style:EBook
Series:Java
Since:2017-09-22
End:....
Total Hours:...
Degree Of Diffculty:2
Degree Of Mastery:2
Practical Level:2
Desired Goal:2
Archieve Goal:....
Gerneral Evaluation:...
Writer:kingdelee
Related Links:
http://www.cnblogs.com/kingdelee/
1.泛型
泛型可以使用在类、方法、对象中
1.1 继承泛型
在一个类中,父类显式写明的泛型,子类不能再重复写,只能写子类自己的
// 1. 在一个类中,父类显式写明的泛型,子类不能再重复写,只能写子类自己的 public class A1<T> extends Apple<String> { // 正确重写了父类的方法,返回值 // 与父类Apple<String>的返回值完全相同 public String getInfo() { return "子类" + super.getInfo(); } public T getT(T t){ System.out.println("A1:" + t.toString()); return t; } /* // 下面方法是错误的,重写父类方法时返回值类型不一致 public Object getInfo() { return "子类"; } */ public static void main(String[] args) { AA<String, Integer> stringIntegerAA = new AA<>(); stringIntegerAA.getT("a"); } } class AA<T, C> extends A1<T>{ @Override public T getT(T o) { super.getT(o); System.out.println("AA:"); return o; } }
1.2 泛型不能作为静态对象的申明,不能作为静态方法的形参,但是可以作为静态方法的方法体中的参数使用。
public class R<T> { // 下面代码错误,不能在静态变量声明中使用类型形参 // static T info; T age; public void foo(T msg){} // 下面代码错误,不能在静态方法声明中使用类型形参 // public static void bar(T msg){} // <T>只能写在void之后,不能写在static之后 // public <T>static void bar(Object msg){} // 泛型不能作为参数传进来,却能作为方法中的参数来使用 public static <T>void bar(Object msg){ T t = null;} }
1.3 数组和集合中泛型问题
假设Foo是Bar的子类,G<Foo>和G<Bar>之间不存在继承关系,即G<Foo>不能传给G<Bar>,但Foo[] 是 Bar[]的子类,Foo[]可以传给Bar[]
3. 泛型通配符
3.1 <?>使用这种时,他的类型就是Object,往往作为方法中传递的形参使用,而不是申明使用。在做形参使用时,往往与 extends 或者 super来一起使用,限定参数范围。
public void drawAll(List<? extends Shape> shapes) { for (Shape s : shapes) { s.draw(this); } }
3.2 泛型与通配符
当某个泛型不会作为返回值,也不会被某些参数依赖,则使用通配符更优
3.3 构造器泛型的申明语法,即 new<T> A();
class MyClass<E> { public <T> MyClass(T t) { System.out.println("t参数的值为:" + t); } } public class GenericDiamondTest { public static void main(String[] args) { // MyClass类声明中的E形参是String类型。 // 泛型构造器中声明的T形参是Integer类型 MyClass<String> mc1 = new MyClass<>(5); // 显式指定泛型构造器中声明的T形参是Integer类型, MyClass<String> mc2 = new <Integer>MyClass<String>(5); // MyClass类声明中的E形参是String类型。 // 如果显式指定泛型构造器中声明的T形参是Integer类型 // 此时就不能使用"菱形"语法,下面代码是错的。 // MyClass<String> mc3 = new <Integer> MyClass<>(5); } }
3.4 类型推断
// 1.类型推断, A.<T>a(); class MyUtil<E> { public static <Z> MyUtil<Z> nil() { return null; } public static <Z> MyUtil<Z> cons(Z head, MyUtil<Z> tail) { return null; } E head() { return null; } } public class InferenceTest { public static void main(String[] args) { // 可以通过方法赋值的目标参数来推断类型参数为String MyUtil<String> ls = MyUtil.nil(); // 无需使用下面语句在调用nil()方法时指定类型参数的类型 MyUtil<String> mu = MyUtil.<String>nil(); // 可调用cons方法所需的参数类型来推断类型参数为Integer MyUtil.cons(42, MyUtil.nil()); // 无需使用下面语句在调用nil()方法时指定类型参数的类型 MyUtil.cons(42, MyUtil.<Integer>nil()); // 希望系统能推断出调用nil()方法类型参数为String类型, // 但实际上Java 8依然推断不出来,所以下面代码报错 // String s = MyUtil.nil().head(); String s = MyUtil.<String>nil().head(); } }