简体   繁体   English

Java编译器如何处理类型之外的缺失类型参数 <E> ,例如 <E extends Foo>

[英]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以及extendssuper之间的区别

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

TL;DR TL; DR

They are the same. 他们是一样的。

Long Form 长表

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.

相关问题 在Java类型参数中,确实如此 <? extends E> 仅指严格的亚型? 还是E也足够了? - In Java type arguments, does <? extends E> mean strictly subtypes only? or would E also suffice? 如何创建E类型的Java列表扩展Comparable <? super E> - How to create Java List of Type E extends Comparable<? super E> 如何确定哪些 Java 类型(例如 LocalDate)是安全可散列的? - How to determine which Java types (e.g. LocalDate) are safely hashable? 如何为BitSet类型的元素创建SortedSet(例如TreeSet) - How to create SortedSet (e.g. TreeSet) for elements of type BitSet 可以使用反射来获得具体的实现类型(例如Class <? extends MyInterface> )? - Can reflection be used to get a concrete implementing type (e.g. Class<? extends MyInterface>)? 确定空通配符集合的类型(例如,列表 <? extends Number> ) - Determine type of empty wildcard collection (e.g. List<? extends Number>) Java Path 如何转换为例如 InputStream - How is Java Path converted to e.g. InputStream 服务器浏览器如何在游戏中工作? - How does a server browser e.g. in games work? 如何在java中重新绘制特定区域(例如圆圈)? - How to repaint a specific area (e.g. circle) in java? 如何用Java中的值创建类似类型驱动选择的内容(例如,图片) - How to create something like a type driven selection with values in java (e.g. picture)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM