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