JavaのVarとval?

翻訳者から :この記事の著者は、 Joda TimeライブラリーとJava Time APIの著者であるStephen Colebourneです。


Javaでローカル変数型の推論を追加する必要がありますか? ちょうど今、Java開発チームがこの質問をしました。

ローカル変数のタイプの推論


JEP-286は、新しい擬似キーワード(「予約された型名」と解釈される)を使用してローカル変数の型推論を追加することを提案しています。

多くの場合、ローカル変数のタイプを明示的に示す必要はありません。 開発者が省略できるように、静的型付けを犠牲にすることなく、必要な手続きの数を減らすことにより、Javaでの開発を簡素化します。

いくつかのキーワードの提案が利用可能です:


現在の実装戦略では、これらのオプションの前でfinalキーワードが引き続き有効であり、その結果、これらの方法のいずれかで不変変数を宣言できることが示唆されています。


したがって、実際には、選択は次の組み合わせのいずれかになります。


一般に、この機能は私を喜ばせず、Javaがさらに良くなるかどうかはわかりません。 もちろん、IDEで作業する場合、型情報の欠如はスムーズになります。 ただし、通常IDEの助けを借りずに行われるため、多くの場合、これによりコードのレビューが難しくなると思います。 C#プログラミング契約では、この機能の過度の使用を推奨していないことにも注意してください。
代入の右側の式のタイプが明らかでない場合は、 var使用しないでください。
タイプを決定するために変数の名前に依存しないでください。 それは真実ではないかもしれません。

上記にもかかわらず、私はこの改善の実装を停止する可能性がほとんどないと思います。 したがって、この記事の残りの部分では、提案されたオプションから適切なオプションを選択する方法について説明します。

Javaに最適


この改善が発表されたとき、SkalaとKotlinの支持者はvarvalを使用することを自然にアドバイスし始めました。 ただし、前任者の経験から学ぶことは常に有用ですが、これはそのようなオプションがJavaにとって理想的であることを意味しません。

Javaの最適なオプションが異なる主な理由は、ストーリーです。 ScalaとKotlinでは、この機会は最初からのものでしたが、Javaではそうではありませんでした。 そして、歴史的な理由により、 valまたはlet使用がJavaに適さない理由を示したいと思います。

次のコードを検討してください。
 public double parSpread(SwapLeg leg) { Currency ccyLeg = leg.getCurrency(); Money convertedPv = presentValue(swap, ccyLeg); double pvbp = legPricer.pvbp(leg, provider); return -convertedPv.getAmount() / pvbp; } 

ここでは、ローカル変数タイプを派生させることで問題なく動作します。 しかし、コードの読み取り時にいずれかの行の変数の型が不明確であり、C#の推奨事項に従って明示的に指定することにしたと仮定します。
 public double parSpread(SwapLeg leg) { val ccyLeg = leg.getCurrency(); Money convertedPv = presentValue(swap, ccyLeg); val pvbp = legPricer.pvbp(leg, provider); return -convertedPv.getAmount() / pvbp; } 

すべて順調です。 しかし、もしこのコードがコマンドによって書かれていて、規則がローカル変数をfinalという単語で明示的にマークすることを意味する場合はどうでしょうか?
 public double parSpread(final SwapLeg leg) { val ccyLeg = leg.getCurrency(); final Money convertedPv = presentValue(swap, ccyLeg); val pvbp = legPricer.pvbp(leg, provider); return -convertedPv.getAmount() / pvbp; } 

突然混乱がありました。 一部の場所では、単語final不変変数を示すために使用され、他の場所では単語valます。 すべてを台無しにするのはこの混合物であり、同時に、この問題はロックとコトリンにはありません。

(おそらく、各ローカル変数にfinalを使用しないのでしょうか?私は使用しません。しかし、これは非常に合理的な標準であり、開発セキュリティを改善し、エラーを減らすために考案されたものです。)

そして、これが代替案です。
 public double parSpread(final SwapLeg leg) { final var ccyLeg = leg.getCurrency(); final Money convertedPv = presentValue(swap, ccyLeg); final var pvbp = legPricer.pvbp(leg, provider); return -convertedPv.getAmount() / pvbp; } 

Javaの場合、これははるかに一貫しています。 finalという単語は、不変の変数を指定するためのユビキタスなメカニズムであり続けています。 そして、私のように、どこでもfinalに署名する必要があると思わない場合は、単にそれを削除します:
 public double parSpread(final SwapLeg leg) { var ccyLeg = leg.getCurrency(); Money convertedPv = presentValue(swap, ccyLeg); var pvbp = legPricer.pvbp(leg, provider); return -convertedPv.getAmount() / pvbp; } 

私は多くの読者がこの場所で持っている異議を理解しています。 同様に、2つの新しい「キーワード」があり、1つは可変ローカル変数、もう1つは不変ローカル変数であり、不変バージョンをより頻繁に使用するように両方を同じ長さ(または可変の単語でも長くする)にする必要があります。

しかし、Javaではそれほど単純ではありません。 「 final 」という言葉は長年にわたって存在しfinalいます。 この事実に目を向けると、コードはくて一貫性のない混乱に変わります。

おわりに


個人的には、ローカル変数のタイプの結論がまったく好きではありません。 しかし、まだそれを行うことに決めた場合、既存の言語にうまく適合することが必要です。

私の立場は、 vallet Javaには適さないということです。なぜなら、 finalという単語がすでに存在し、明確な意味を持っているからです。 varfinal var持つバリアントは完全でfinal varませんが、これが既存の言語に適合する唯一の組み合わせであると思います。

Source: https://habr.com/ru/post/J280188/


All Articles