Re: [问题] 关于泛型 资料型态的疑问

楼主: JustinHere (良葛格)   2015-05-28 18:07:11
※ 引述《LaPass (LaPass)》之铭言:
: //下面这段OK
: List<A> lista;
: List<C> listc=new ArrayList<>();
: listc.add(new C());
: //lista = listc; // X
: lista=(List)listc; //OK
: A a=lista.get(0); //OK
: System.out.print(a.getStr()); //印出 C
你可以了解一下“共变性”…
Java的泛型并不具有共变性,不过可以使用型态通配字符?与extends来宣告变量,使其达
到类似共变性。
http://openhome.cc/Gossip/Java/Generics-extends.html
如果需要达到类似共变性的功能,可以用 ? extends,这样就不用 CAST 来关掉编译器
型态检查功能 …
List<? extends A> lista;
List<C> listc = new ArrayList<>();
listc.add(new C());
lista = listc; // OK,类似共变性
A a=lista.get(0); //OK
System.out.print(a.getStr()); //印出 C
: //让我们反过来试试看,这样也是ok的
: List<A> lista=new ArrayList<>();
: List<C> listc;
: lista.add(new C()); //OK 自动转型
: //listc = lista; // X
: listc=(List)lista; //OK
: A a=listc.get(0); //OK
: System.out.print(a.getStr()); //印出C
可以研究一下“逆变性”,如果Node<A>视为一种Node<B>,则称Node具有
逆变性(Contravariance)。Java泛型并不支援逆变性,可以使用型态通配字符?
与super来宣告,以达到类似逆变性的效果
http://openhome.cc/Gossip/Java/Generics-super.html
如果需要达到类似逆变性的功能,可以用 ? super,这样就不用 CAST 来关掉编译器
型态检查功能 …
List<A> lista=new ArrayList<>();
List<? super C> listc;
Lista.add(new C()); //OK 这不是自动转型,这是符合 is-a 关系
listc = lista; // OK,类似逆变性
A a= (A) listc.get(0); // 确定没问题,关掉编译器型态检查
System.out.print(a.getStr()); //印出C
: //编译OK但是执行不OK
: List<A> lista=new ArrayList<>();
: List<C> listc;
: lista.add(new A()); //OK 自动转型
: //listc = lista; // X
: listc=(List)lista; //OK
: C c=listc.get(0); //编译OK,执行错误
: ClassCastException: A cannot be cast to C
因为 CAST 实际上是关掉编译器型态检查的功能,实际上 listc 参考的实例,
当中是维护了一串 A 实例,你又编译时期叫编译器住嘴,当然执行时期出错就得
自行收拾了 … XD
: //再来看一个更惊悚的
: List<A> lista=new ArrayList<>();
: List<B> listb;
: listb=(List)lista; //OK
: listb.add(new B()); //OK.... 慢著,这很明显有问题啊!
: B b=listb.get(0); //可是还是被我拿出来了
: A a=lista.get(0); //编译ok,执行时才出错
: ClassCastException: B cannot be cast to A
这不是惊不惊悚的问题,CAST 是关掉编译器型态检查功能,在不确定内容物究竟为何
,就进行 cast(或者是故意 cast),想不出错很难吧! … XD
简单来说,只有在确实清楚实例的型态为何下,再进行 CAST(也就是要编译器别囉嗦)
…XD
: 因为java在运行时根本不会记住那个物件的泛型型别
是的,泛型提供的资讯只是给编译器看的 ...

Links booklink

Contact Us: admin [ a t ] ucptt.com