簡體   English   中英

Eclipse Java編譯器和OpenJDK編譯器(Java 8)之間的類型推斷差異

[英]Type inference discrepancy between Eclipse Java compiler and OpenJDK compiler (Java 8)

我正在做一些元編程,在其中解析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 ...
   }

但是,當然,未經檢查的演員陣容很難看。 認為這應該是安全的,因為在這里任意引入類型參數ValueType只是為了捕獲通配符。 在處理過程中,我只需要進一步實例化一個XmlAdapter並對其進行unmarshal 在運行時,不會發生任何異常。

因此,我的問題是,首先是應該編譯原始代碼,其次,這是Eclipse編譯器還是OpenJDK編譯器錯誤?

不是錯誤。 您在這里使用嵌套泛型。

Class<? extends XmlAdapter<?, BoundType>> Class<? extends XmlAdapter<?, BoundType>>Class<? extends XmlAdapter<ValueType, 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) {

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM