2016-06-29 7 views
2

私はenumenum値のカスタム文字列変換関数を作る方法があります:私は私の特定の列挙のための関数を作るための方法を使用したい作曲機能

public enum MyEnum { 
    DUMMY; 
} 

public <E extends Enum<E>> Function<E, String> stringify(String suffix) { 
    return enumValue -> enumValue.name() + suffix; 
} 

次のように入力します。

public void test() { 
    Function<MyEnum, String> f = stringify(""); 
} 

これは機能しますが、文字列の後続処理を行う必要があります。たとえば、後続処理が単なる恒等関数であるとします。

コンパイルエラーが発生しました。 Eclipseの(ネオン)は言う:

型の不一致は:Function<Enum<Enum<E>>,String>からFunction<Test.MyEnum,String>

javacに変換することはできませんと言う:

error: incompatible types: no instance(s) of type variable(s) V,T#2 exist so that Function<E,V> conforms to Function<MyEnum,String> 
     Function<MyEnum, String> f = stringify("").andThen(Function.identity()); 
                ^
    where V,R,T#1,T#2,E are type-variables: 
    V extends Object declared in method <V>andThen(Function<? super R,? extends V>) 
    R extends Object declared in interface Function 
    T#1 extends Object declared in interface Function 
    T#2 extends Object declared in method <T#2>identity() 
    E extends Enum<E> 

Function.identity()の戻り値の型は、引数の型と同じですだから、私はそれが全体の結果をFunction<MyEnum, String>以外の何かに変えるのか分かりません。私は特に、EclipseエラーメッセージのEnum<Enum<E>>で混乱しています。私は変数に中間結果を割り当てることで問題を回避できることに気付きました

public void test() { 
    Function<MyEnum, String> f1 = stringify(""); 
    Function<MyEnum, String> f2 = f1.andThen(Function.identity()); 
} 

が、私はむしろ、その可能であれば避けたいです。

このタイプの不一致はなぜ発生しますか?それを解決する最善の方法は何ですか?

答えて

2

これはジェネリックな境界問題です。このステートメントで

Function<MyEnum, String> f = stringify("").andThen(Function.identity()); 

コンパイラは、文字列化のためのバウンドを知らない(「」)ので、同様Function.identity()のためのバウンドを推測することはできません。この問題を解決するには

、あなたがstringify("")にバインドを追加する必要があります:あなたは、単に<MyEnum>stringify("")を書き込むことはできませんので、

Function<MyEnum, String> f = this.<MyEnum>stringify("").andThen(Function.identity()); 

予告thisキーワードは、同様に追加されます。

stringify("")メソッドは、クラスutilの静的な一部からのものである場合、それは代わりに従うようになります。

Function<MyEnum, String> f = MyUtils.<MyEnum>stringify("").andThen(Function.identity()); 
+1

'andThen'コールがなければ、コンパイラは' '文字列化(「」)の型限界を知っていますそれは 'f'の宣言された型から来ているからです。 'andThen'コールで' stringify( "") 'の結果は' f'に直接代入されなくなりましたが、コンパイラは 'andThen'に入る型がタイプはそれから出てくる。しかし、型推論がそれほど後ろ向きに働くことはできないと言っているようです。 – Wyzard

+1

私は少しあなたを混乱させるかもしれません。'.andThen'の観点から推論された型は、型に明示的にバインドされていないとき、実際には' <? Enum > 'を拡張します。これはまさに 'stringify'メソッドで定義したものです。だからあなたの質問では、効果的に 'Function <? Enum 、String>を 'Function 'に拡張することはできません。 – kazenorin