Java上的通配符和子类型

时间:2014-08-08 04:07:01

标签: java wildcard subtyping

我刚刚开始学习Java上的通配符和子类型,并尝试测试我学到的东西。

假设:

Class A { public int y=1; }
Class B extends A { public int x=2; }

主要:

List<B> lb = new ArrayList<>();
lb.add(new B());
System.out.println(lb.get(0).y); //Displays member y of Class A
List<? extends A> la = lb;
System.out.println(la.get(0).y); //Can access member y of Class A

List<A> la1 = new ArrayList<>();
la1.add(new A());
System.out.println(la1.get(0).y); //Displays member y of Class A
List<? super B> lb1 = la1;
System.out.println(lb1.get(0).y); //Cannot access member y of Class A? Why?

我不明白为什么我不能使用Lower Bounded Wildcards访问成员y,而可以使用Upper Bounds Wildcards。我错过了什么吗?

4 个答案:

答案 0 :(得分:1)

考虑

Interface X { ... }
Class A { public int y=1; }
Class B extends A implements X { public int x=2; }

List<? super B> lb1 = la1;

现在,lb1中的对象可能与AB完全无关,只要它们实现X即可。编译器无法知道lb1.get(0)有成员y

更多&#34;具体&#34;例如:

Class X { ... }
Class A extends X { public int y=1; }
Class B extends A { public int x=2; }

使用lb1中的此层次结构对象可以是X类型,其中没有成员y

答案 1 :(得分:0)

U的上限:必须至少为U。任何U都有,你可以使用。

L的下限:最多可以L(同时保留在其层次结构中),但不保证会出现这种情况。

答案 2 :(得分:0)

简单来说,你不能得到&#39; TYPE&#39;从使用关键字&#39; SUPER&#39; ...

构建的列表中

的System.out.println(lb1.get(0).Y); //这是错误的,因为你期待A / B型

我猜,以下内容应该有效

的System.out.println(((A)(lb1.get(0)))Y。);

因为你只能从这个列表中获得一个OBJECT ...你需要投射它以获得你的&#39; TYPE&#39;

答案 3 :(得分:-1)

只需更新一行

((A)lb1.get(0)).y