java - Eclipse Java 编译器和 OpenJDK 编译器之间的类型推断差异 (Java 8)

标签 java eclipse type-inference

我正在做一些元编程,其中解析 JAXB bean,特别是 XmlAdapter 注释。我遇到了这样的情况:Eclipse Oxygen (4.7.2) 的编译器对某些使用类型推断的方法完全满意,但 OpenJDK 编译器 (javac 1.8.0_131) 对它们感到窒息。

我已将主要结构提取到此 MWE 中:

import java.time.LocalDate;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class Main<BoundType>
{
   public void parse( Class<? extends XmlAdapter<?, BoundType>> adapterClass ) throws Exception
   {
      process( adapterClass );
   }

   private <ValueType> void process( Class<? extends XmlAdapter<ValueType, BoundType>> adapterClass ) throws Exception
   {
      // Do something with adapterClass ...
   }

   private static final class SomeAdapter extends XmlAdapter<String, LocalDate>
   {
      @Override
      public LocalDate unmarshal( String v ) throws Exception
      {
         return v == null ? null : LocalDate.parse( v );
      }

      @Override
      public String marshal( LocalDate v ) throws Exception
      {
         return v == null ? null : v.toString();
      }
   }

   public static void main( String[] args ) throws Exception
   {
      Main<LocalDate> main = new Main<>();

      main.parse( SomeAdapter.class );
   }
}

OpenJDK 编译器产生此错误:

/[...]/WildcardProblem/src/Main.java:21: error: method process in class Main<BoundType> cannot be applied to given types;
      process( adapterClass );
      ^
  required: Class<? extends XmlAdapter<ValueType,BoundType>>
  found: Class<CAP#1>
  reason: cannot infer type-variable(s) ValueType
    (argument mismatch; Class<CAP#1> cannot be converted to Class<? extends XmlAdapter<ValueType,BoundType>>)
  where ValueType,BoundType are type-variables:
    ValueType extends Object declared in method <ValueType>process(Class<? extends XmlAdapter<ValueType,BoundType>>)
    BoundType extends Object declared in class Main
  where CAP#1 is a fresh type-variable:
    CAP#1 extends XmlAdapter<?,BoundType> from capture of ? extends XmlAdapter<?,BoundType>

我可以通过修改方法 process 来解决编译器错误,如下所示:

   private <ValueType> void process( Class<? extends XmlAdapter<?, BoundType>> adapterClass ) throws Exception
   {
      @SuppressWarnings( "unchecked" )
      Class<? extends XmlAdapter<ValueType, BoundType>> capturedAdapterClass = (Class<? extends XmlAdapter<ValueType, BoundType>>) adapterClass;

      // Do something with adapterClass ...
   }

但是,当然,未经检查的 Actor 阵容是丑陋的。我相信它应该是安全的,因为这里任意引入类型参数ValueType只是为了捕获通配符。我只需要在处理中进一步实例化 XmlAdapter 并对其调用 unmarshal 即可。运行时不会出现异常。

所以我的问题是,首先,原始代码是否应该编译,其次,这会是 Eclipse 编译器还是 OpenJDK 编译器错误吗?

最佳答案

不是错误。您正在这里使用嵌套泛型。

Class<? extends XmlAdapter<?, BoundType>>Class<? extends XmlAdapter<ValueType, BoundType>> 不同.

您必须将方法签名更改为:

public <ValueType> void parse( Class<? extends XmlAdapter<ValueType, BoundType>> adapterClass )

或者像以前一样进行转换。

<小时/>

更简单的例子:

public void parse2(List<? extends Optional<?>> optionals) {
    process2(optionals); // compilation error
}

public <T> void process2(List<? extends Optional<T>> optionals) {

}

关于java - Eclipse Java 编译器和 OpenJDK 编译器之间的类型推断差异 (Java 8),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49451943/

相关文章:

java - 我可以通过自定义方法对用户进行身份验证吗?

java - 添加 JScrollpane,其中 JPanel 比 JFrame 大

c# - 类型删除 : Java vs C#

java - 为什么我无法将 Base64 编码图像插入电子邮件 HTML Velocity 模板?

java - 如何将 Firestore 中的 GeoPoint 转换为 LatLng

visual-studio - 用 eclipse 做书签

java - 如何使用 jdk 1.6.0_20 在 Eclipse 3.6 中配置 tomcat 7?

java - 数组列表扫描器循环退出功能

c# - 为什么编译器无法推断对象数组类型?

generics - 为什么泛型的推断不是 "transitive"?