2016-07-14 5 views
4

Java 1.7から1.8へのコードベースの移行中に、「メソッド...は引数に適用できませんいくつかのコードの場所では、すべてジェネリックスの使用法と同じパターンに従います。Java 8のジェネリックメソッドは、Eclipseの引数には適用されません

Windows 7でほとんどEclipse Mars(4.5.2)を使用していますが、Neon(4.6)でも動作を確認できました。 Javacおよびecjの1.7準拠レベルでは、エラーなしにコードをコンパイルできます。ここで

は、最小完全、かつ検証可能な例である:今doSomething方法でコメントアウト行を切り替え

public class ComplexInterfaceTest { 

    public static class Foo {} 

    public interface Bar { 
    void print(); 
    } 

    public static class SubFooBar extends Foo implements Bar { 
    public void print() { 
     System.out.println(this.getClass().getSimpleName()); 
    } 
    } 

    public static class FooBar<T extends Foo & Bar> { 
    public static <T extends Foo & Bar> FooBar<T> makeFooBar() { 
     return new FooBar<>(); 
    } 

    public void create(T value) { 
     value.print(); 
     return; 
    } 
    } 

    public static class Base<T extends Foo> {} 

    public static class Subclass extends Base<SubFooBar> { 
    public void doSomething(SubFooBar value) { 
//  FooBar.<SubFooBar>makeFooBar().create(value); 
     FooBar.makeFooBar().create(value); 
    } 
    } 

    public static void main(String[] args) { 
    new Subclass().doSomething(new SubFooBar()); 
    } 

} 

は、コンパイルするコードになりますので、我々は回避策を持っています。それでもエラーメッセージがクラスSubFooBarFooを拡張するように、右ではないようで、それが<T extends Foo & Bar> FooBar<T> makeFooBar()に必要とされる<T extends Foo & Bar>の契約を、満たし、そう実際にTはIMO SubFooBarにバインドする必要がありますので、Barを実装しています。

は、私は同様の質問を検索し、これらが見つかりました:私はそれは ecjバグかもしれないと思わせる Differences in type inference JDK8 javac/Eclipse Luna? Type Inference Compiler Error In Eclipse with Java8 but not with Java7

を。このコースでは私もEclipse Bugzillaに見えたが、同等の何かを見つけることができませんでした、私はこれらを見ました:

  • 430686が固定検証される - 鉱山はスカラー型に関係しています
  • 440019ではない - 私のいない
  • 492838、448793は、ワイルドカードでなければならない - 鉱山はない

Eclipse Bugzilla議論は、私は必ずしも従うことができますecjの内部動作に関する詳細に満ちています。しかし、私が理解しているのは、Eclipseコンパイラがを厳密に守らなければならず、javac(それが間違っていた場合)ではないので、必ずしもecjのバグである必要はありません。 ecjバグでなければ、コードをコンパイルするにはjavacのバグだったはずです。

私が関心を持っているのは、自分のコードスニペットの型推論プロセスを分析できる人たちです。コードがコンパイルされているか、コーディングにエラーがありましたか?欠陥が497905が(ステファンハーマンは受け入れ答え以下の彼のコメント内のリンクを掲載している)ID番号を持っており、現在は次のとおりです。私は、EclipseのBugzillaに私のレポートの結果を掲示することを約束したよう

EDIT

v4.7をターゲットとしています。

方法

public void doSomething(SubFooBar value) { 
    FooBar.makeFooBar().create(value); 
} 

+1

Eclipse Bugzillaに関するバグレポートを投稿しました。回答を投稿します。 –

答えて

2

SubFooBarと推測されることはありませんmakeFooBar()メソッドの型パラメータT。後でSubFooBarのインスタンスをcreateメソッドに渡すことは、前の呼び出し式FooBar.makeFooBar()の型には影響しません。

この新しい機能は、チェーンメソッド呼び出しの受信者式では機能しないため、これはJava 8のターゲットの型変更では変更されません。

だから、すべてのバージョンで、makeFooBar()呼び出しのTのために推論タイプは、交差点の種類Foo & Barとなりますので、結果の型はFooBar<Foo&Bar>です。これは、エディタのツールチップが別のものを表示したとしても、Eclipseが推論するものです。

これはFooBar<Foo&Bar>.create(…)Foo&BarSubFooBarのインスタンスがFooを拡張しBarが互換性のある実装期待どおりにcreate方法SubFooBarインスタンスを渡すことができることを意味します。

これは、Eclipseが

public void doSomething(SubFooBar value) { 
    FooBar.makeFooBar().create((Foo&Bar)value); 
} 

をキャスト適切な型を挿入すると、コンパイラエラーが離れて行かせるように、他のすべてのコンパイラと同じ型を推論していることを証明することが可能です。したがって、ここでの問題は型推論ではありませんが、SubFooBarFoo & Barに割り当てられないとEclipse版では考えています。

+2

これは私の分析にも一致します(https://bugs.eclipse.org/bugs/show_bug.cgi?id=497905#c1) –

+0

基本的にTは 'Foo&Bar'であり、SubFooBarは' Foo&Bar'コードですコンパイルすべきだった。知っておいて、ありがとう! –

+1

私はそれに時間をとらせました - 私は追加することができることはあまりないと思います。正しい理由が間違っていても、私のコードが正しいと思われるので、問題は 'Eclipse 'バージョン4.7。 –

関連する問題