私は依存性注入のためのファクトリーを作成するためのエレガントな方法を探しています。私の場合、ファクトリーは1つの引数のコンストラクタを呼び出すだけで済みます。私はこれを見つけました答えFunction<ParamType, ClassToNew>
そのような目的のためにを使用する方法を概説します。
しかし、私の問題は、私の場合、ctor が何らかのチェック例外をスローすることを宣言していることです。
理解できないのは、それを作ること関数そのコンストラクタへのメソッド参照を使用しても機能しません。次のように:
import java.util.function.Function;
public class Mcve {
public Mcve(String s) throws Exception {
// whatever
}
public static void main(String[] args) {
Function<String, Mcve> mcveFactory = Mcve::new;
}
}
は、 の「未処理の例外: java.lang.Exception」について教えてくれますMcve::new
。このコードはないコンストラクターを呼び出します。
2つの質問:
- なぜエラーになるのでしょうか?上記のコードはないctor を (まだ) 呼び出しますか?
- このパズルを解くエレガントな方法はありますか?(
throws Exception
私main()
のないヘルプ )
ベストアンサー1
ThrowingFunction
をスローするメソッドを 1 つ持つカスタム インターフェイスを提供する必要がありますException
。
public interface ThrowingFunction<ParameterType, ReturnType> {
ReturnType invoke(ParameterType p) throws Exception;
}
public class Mcve {
public Mcve(String s) throws Exception {
// whatever
}
public static void main(String[] args) {
ThrowingFunction<String, Mcve> mcveFactory = Mcve::new;
}
}
このアプローチを使用すると、mcveFactory.invoke("lalala");
コンストラクターによってスローされた例外を強制的に処理することになります。
エラーの原因は、保存する実際の関数参照 (用語については 100% 確信はありません) が例外をスローし、そのため型が一致しないことです。もしMcve::new
関数内に保存すれば、関数を呼び出す人はもう知っているをException
スローできます。例外が実際にスローされた場合、何が起こるでしょうか? 例外をスローすることも、それを破棄することも機能しません。
代替案: 最終的に を実際に取得する必要がある場合は、Function<String, Mcve>
コンストラクターを呼び出して例外をキャッチし、それを破棄するか、チェックされていない 内にラップして再スローする関数 (またはラムダ) を記述する必要がありますRuntimeException
。
public class Mcve {
public Mcve(String s) throws Exception {
// whatever
}
public static void main(String[] args) {
Function<String, Mcve> mcveFactory = parameter -> {
try {
return new Mcve(parameter);
} catch (Exception e) {
throw new RuntimeException(e); // or ignore
}
};
}
}
エラーメッセージ自体は、メソッドを実際に呼び出したときに通常表示されるため、少なくとも少し誤解を招くものであると私は主張します。最初のサブ質問で生じた混乱は確かに理解できます。次のように述べる方が明確になります(残念ながら不可能ですが)。
互換性のないタイプ
Function<String,Mcve>
vs.Function<String,Mcve> throws Exception