[英]How does the java compiler treat missing type arguments for types besides <E>, e.g., <E extends Foo>
I understand the difference between these 3 lines of code, 我了解这三行代码之间的区别,
ArrayList list1 = new ArrayList();
ArrayList<Object> list2 = new ArrayList<Object>();
ArrayList<? extends Object> list3 = new ArrayList<? extends Object>();
but let's say I have this example class Foo, 但是,假设我有这个示例类Foo,
class Foo<T extends Bar> {
// ...
}
how does the compiler handle these differently, if at all? 编译器如何处理这些差异(如果有的话)?
Foo foo1 = new Foo();
Foo<? extends Bar> foo2 = new Foo<? extends Bar>();
I see a lot of examples saying when the type arguments are excluded it doesn't check, but these examples are normally for List
examples and the like where anything can be put in ( public interface List<E> extends Collection<E>
). 我看到很多示例说排除类型实参时不检查,但这些示例通常用于List
示例,以及可以放置任何内容的类( public interface List<E> extends Collection<E>
)。 Does the compiler default to the least restrictive type argument in the declaration when it is omitted or does it simply allow anything? 省略时,编译器会默认使用声明中限制最少的类型参数还是仅允许任何操作吗? Also, if it does default to the declaration, then is there any reason to use the style in foo1
over foo2
? 另外,如果它确实默认为声明,那么是否有任何理由在foo1
不是foo2
使用样式?
Edit: My question is different because it is asking how the compiler treats specific examples and how they differ, the referenced question is about PECS and the difference between extends
and super
编辑:我的问题是不同的,因为它询问编译器如何对待特定示例以及它们如何不同,所引用的问题是关于PECS以及extends
和super
之间的区别
Let's test this by adding a method in Foo: 让我们通过在Foo中添加一个方法来进行测试:
class Foo<T extends Bar> {
void add(T object) {
}
}
Now let's try the two cases: 现在让我们尝试两种情况:
Foo genericFoo = new Foo();
genericFoo.add(new Bar());
genericFoo.add(new Object());
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: stackoverflow.Generics.Foo.add 线程“主”中的异常java.lang.RuntimeException:无法编译的源代码-错误的符号类型:stackoverflow.Generics.Foo.add
So it does check to ensure that the generic object is at least of type Bar
. 因此,它会检查以确保通用对象至少为Bar
类型。
Essentially, these two statements are the same: 本质上,这两个语句是相同的:
Foo<? extends Bar> genericFoo = new Foo<? extends Bar>();
Foo genericFoo = new Foo();
The advantage of the former is that it makes it clearer that you have to add Bar type objects to it. 前者的优点是它使您必须添加Bar类型对象变得更加清晰。
The best way to write it would probably be like this: 最好的编写方式可能是这样的:
Foo<Bar> genericFoo = new Foo<>();
You can still add children of Bar
here, and it's clear that the generic type must be a Bar
. 您仍然可以在此处添加Bar
,很明显,泛型类型必须是Bar
。
They are the same. 他们是一样的。
This is a simple test case. 这是一个简单的测试用例。 In Eclipse there is an error on both put
calls. 在Eclipse中,两个put
调用都出错。 Saying that the method is not applicable for the arguments. 说该方法不适用于自变量。
public class Main {
public static void main(final String[] args) {
final Test test1 = new Test();
final Test<? extends String> test2 = new Test<? extends String>();
test1.put(new Integer(1));
test2.put(new Integer(1));
}
private static class Test<T extends String> {
public void put(final T value) { }
}
}
The compiler gives the same error when either is commented out and they are compiled individually. 当其中一个被注释掉并且它们被单独编译时,编译器会给出相同的错误。
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The method put(String) in the type Main.Test is not applicable for the arguments (Integer)
The method put(capture#1-of ? extends String) in the type Main.Test<capture#1-of ? extends String> is not applicable for the arguments (Integer)
at Main.main(Main.java:9)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.