これがない最初のコンストラクターの場合、誰かが出力0を説明できますか?
確かに-このステートメントはノーオペレーションです:
userId = userId;
userId
パラメータの変数をそれ自体に割り当てるだけです。フィールドには全く触れません。メソッド内で、パラメーターは呼び出されたフィールドをuserId
シャドウuserId
します-したがって、フィールドを参照することを明示的に指定する必要があります。これは、2番目のバージョンが行うことです。
this.userId = userId;
最近のIDEは、最初のバージョンのno-op割り当てを警告付きで強調表示することを期待しています。
(ちなみに、用語について明確にする価値があります。引数はメソッドに提供される値です。パラメーターは、メソッドのシグネチャの一部として宣言される変数です。同様に、プロパティではなくフィールドです。)
編集:パラメータの名前が異なる場合、例:
public User(int id) {
userId = id;
}
その場合、パラメーターはフィールドをシャドウイングせずuserId
、識別子は引き続きフィールドを参照します。識別子の意味を理解することがすべての問題です。最初の例では、単純な名前userId
はパラメータを参照しており、これが問題の原因です。
編集:JLSのセクション6.4.1から:
一部の宣言は、同じ名前の別の宣言によってスコープの一部がシャドウイングされる場合があります。その場合、宣言されたエンティティを参照するために単純な名前を使用することはできません。
..。
dのスコープ全体でのnシャドウという名前のフィールドまたは仮パラメーターの宣言d、dが発生するポイントでスコープ内にあるnという名前の他の変数の宣言。
したがって、この場合、dは正式なパラメーターの宣言であり、userId
dのスコープはコンストラクターです。したがって、コンストラクター全体で、パラメーターはフィールドをシャドウイングします。