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

时间:2018-03-23 14:27:48

标签: java eclipse type-inference

我正在进行一些元编程,我正在解析JAXB bean,尤其是dplyr::fun(argument...)注释。我遇到了Eclipse Oxygen(4.7.2)的编译器完全满足于某些使用类型推断的方法的情况,但是OpenJDK编译器(javac 1.8.0_131)对它们感到窒息。

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

XmlAdapter

OpenJDK编译器产生此错误:

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 );
   }
}

我可以通过修改方法/[...]/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 ... } 只是为了捕获通配符。我只需要在我的处理过程中进一步向下,我将ValueType实例化并在其上调用XmlAdapter。在运行时,不会发生异常。

所以我的问题首先是原始代码应该编译,第二,这是Eclipse编译器还是OpenJDK编译器错误?

1 个答案:

答案 0 :(得分:0)

不是错误。你在这里玩嵌套泛型。

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) {

}