私はJava 8の学習中ですが、私は少し奇妙なものを見つけました。Java 8ローカル変数で呼び出されたメソッド参照
は、次のコードを考えてみましょう:
private MyDaoClass myDao;
public void storeRelationships(Set<Relationship<ClassA, ClassB>> relationships)
{
RelationshipTransformer transformer = new RelationshipTransformerImpl();
myDao.createRelationships(
relationships.stream()
.map((input) -> transformer.transformRelationship(input))
.collect(Collectors.toSet())
);
}
は基本的に、私は私が使用しているDAOのAPIに準拠し するために、異なるタイプのrelationships
と呼ばれる入力セットをマップする必要があります。変換のために、ローカル変数としてインスタンス化する既存のRelationshipTransformerImpl
クラスを使用したいと思います。
は今、ここに私の質問です:
私は次のように上記のコードを変更することだった場合:
public void storeRelationships(Set<Relationship<ClassA, ClassB>> relationships)
{
RelationshipTransformer transformer = new RelationshipTransformerImpl();
myDao.createRelationships(
relationships.stream()
.map((input) -> transformer.transformRelationship(input))
.collect(Collectors.toSet())
);
transformer = null; //setting the value of an effectively final variable
}
ローカル変数transformer
「は事実上なくなっているので、私は明らかに、コンパイルエラーを取得しないだろう最後の"。ただし、ラムダをメソッドリファレンスで置き換える場合は、
public void storeRelationships(Set<Relationship<ClassA, ClassB>> relationships)
{
RelationshipTransformer transformer = new RelationshipTransformerImpl();
myDao.createRelationships(
relationships.stream()
.map(transformer::transformRelationship)
.collect(Collectors.toSet())
);
transformer = null; //setting the value of an effectively final variable
}
私はもはやコンパイルエラーを受け取りません!なぜこれが起こるのですか?ラムダ式を書く2つの方法は同等でなければならないと思っていましたが、明らかに何かが続いています。
なぜラムダのケースで同じことをすることができなかったのかわかりません:lambdaが評価されたときに 'transformer'(または他の変数)の値を取得し、内部の' final'フィールドに格納します。これは、メソッドの参照で行わなければならない効果があります。その変数をラムダ式の本体の外側でのみ変更できるように制限することができます。私は何かが欠けているように感じる。 –
@SotiriosDelimanolisラムダはすぐには評価されません。コンパイル時に生成されるコールサイトだけです。実際のリンケージは、ラムダが 'invokedynamic'で初めて初めて発生します。 – fge
@fge私は_invoked_を意味しませんでした。ラムダ式は、機能インタフェースのインスタンスを生成するために評価されます(http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.4)。コンパイラ(そしてJVM)は 'final'変数の値を単純にクローズし、ローカルに格納することができます。この場合、 –