package Lesson15_generices; //: generics/CovariantArrays.java class Fruit {} class Apple extends Fruit {} class Jonathan extends Apple {} class Orange extends Fruit {} public class CovariantArrays { public static void main(String[] args) { Fruit[] fruit = new Apple[10]; fruit[0] = new Apple(); // OK fruit[1] = new Jonathan(); // OK // Runtime type is Apple[], not Fruit[] or Orange[]: try { // Compiler allows you to add Fruit: fruit[0] = new Fruit(); // ArrayStoreException } catch(Exception e) { System.out.println(e); } try { // Compiler allows you to add Oranges: fruit[0] = new Orange(); // ArrayStoreException } catch(Exception e) { System.out.println(e); } } } /* Output: java.lang.ArrayStoreException: Fruit java.lang.ArrayStoreException: Orange *///:~
package Lesson15_generices; //: generics/Holder.java public class Holder<T> { private T value; public Holder() {} public Holder(T val) { value = val; } public void set(T arg) { value = arg; } public T get() { return value; } public boolean equals(Object obj) { return value.equals(obj); } public static void main(String[] args) { Holder<Apple> Apple = new Holder<Apple>(new Apple()); Apple d = Apple.get(); Apple.set(d); // Holder<Fruit> Fruit = Apple; // Cannot upcast Holder<? extends Fruit> fruit = Apple; // OK Fruit p = fruit.get(); d = (Apple)fruit.get(); // Returns 'Object' try { Orange c = (Orange)fruit.get(); // No warning } catch(Exception e) { System.out.println(e); } // fruit.set(new Apple()); // Cannot call set() // fruit.set(new Fruit()); // Cannot call set() System.out.println(fruit.equals(d)); // OK } } /* Output: (Sample) java.lang.ClassCastException: Apple cannot be cast to Orange true *///:~
/** * 书本:《Thinking In Java》 * 功能:关于系统对于<?>和原生类型的判断,也就是原生类型和涉及无界通配符的类型之间的差异 * 文件:Wildcards.java * 时间:2015年4月20日08:25:59 * 作者:cutter_point */ package Lesson15_generices; public class Wildcards { static void rawArgs(Holder holder, Object arg) { holder.set(arg); //这里holder是泛型的,当使用set方法的时候,这个对象将被向上转型为Object类型的,所以编译器知道这里不安全 holder.set(new Wildcards()); // T t = holder.get(); //这个里面可没有T /* * 所以无论何时,只要使用了原生类型都会放弃编译期的检查 */ } static void unboundedArg(Holder<?> holder, Object arg) { // holder.set(arg); //这里使用一个Object参数会报错,虽然实际上还是转化为Object,但是编译器认为Holder<?>是具有某种具体类型的同构集合 // holder.set(new Wildcards()); // holder = new Holder<Object>(); //这样用 Object obj = holder.get(); //返回的就是一个Object类型 } static <T> T exact1(Holder<T> holder) { T t = holder.get(); return t; } static <T> T exact2(Holder<T> holder, T arg) { holder.set(arg); T t = holder.get(); return t; } static <T> T wildSubtype(Holder<? extends T> holder, T arg) { // holder.set(arg); //出错,这个类型是一个继承自T的类型,也就是无法放入超类 T t = holder.get(); return t; } static <T> void wildSupertype(Holder<? super T> holder, T arg) { holder.set(arg); //出错,这个类型是一个继承自T的类型,也就是无法放入超类 // T t = holder.get(); //这里返回的就不是T的类型了,因为T在传入的时候是可以是任何的T的超导类,所以这里用T来返回时不安全的,只能是Object类型 Object t = holder.get(); } public static void main(String[] args) { Holder raw = new Holder<Long>(); //或者 raw = new Holder(); Holder<Long> qualified = new Holder<Long>(); Holder<?> unbounded = new Holder<Long>(); Holder<? extends Long> bounded = new Holder<Long>(); Long lng = 1L; rawArgs(raw, lng); rawArgs(qualified, lng); rawArgs(unbounded, lng); rawArgs(bounded, lng); unboundedArg(raw, lng); unboundedArg(qualified, lng); unboundedArg(unbounded, lng); unboundedArg(bounded, lng); // Object r1 = exact1(raw); //警告, Long r2 = exact1(qualified); Object r3 = exact1(unbounded); // Must return Object Long r4 = exact1(bounded); Long r6 = exact2(qualified, lng); Long r10 = wildSubtype(qualified, lng); /* * static <T> T wildSubtype(Holder<? extends T> holder, T arg) { // holder.set(arg); //出错,这个类型是一个继承自T的类型,也就是无法放入超类 T t = holder.get(); return t; } */ //Object r11 = wildSubtype(unbounded, lng); //不能放入超类,只能是Holder的导出类 Long r12 = wildSubtype(bounded, lng); wildSupertype(qualified, lng); } }
输出:
这里面会报错,根据main函数里面各种不同的参数传值
【ThinkingInJava】39、对于<?>和原生类型的判断
原文地址:http://blog.csdn.net/cutter_point/article/details/45814883