2017-02-18 5 views
1

私は、メソッドシグネチャでfinalキーワードを使用すると、java.lang.Number(例:java.lang 。長いです)?メソッドにjava.lang.Numberのインスタンスを渡すときの最終的なキーワード

Javaパスオブジェクトが価値観に敬意を表しているので意味がないと思います。つまり、javaは元の参照のコピーをメソッドに渡します。この番号の値の変更は、メソッド外では見えません。したがって、メソッドがメソッド内の値を変更するかどうかは関係ありません。

もちろん、pojoをメソッドに渡すと、最終的なキーワードを使用するのは意味がありますが、別のシナリオです。

java.lang.Number型のデモ

public class Demo { 

    public static void main(String[] args) { 
     Long longValue = 1L; 
     System.out.println("Long before: " + longValue); 
     System.out.println(trickyMethod(longValue)); 
     System.out.println("Long after: " + longValue); 

     BigInteger bigIntegerValue = BigInteger.ONE; 
     System.out.println("BigInteger before: "+ bigIntegerValue); 
     System.out.println(trickyMethod(bigIntegerValue)); 
     System.out.println("BigInteger after: " + bigIntegerValue); 
    } 

    private static String trickyMethod(Long value) { 
     value = 10L; 
     System.out.println(" trickyMethod: " + value); 

     if (value.equals(10L)) 
      return " equal"; 
     else 
      return " different"; 
    } 

    private static String trickyMethod(BigInteger value) { 
     value = BigInteger.TEN; 
     System.out.println(" trickyMethod: " + value); 

     if (value.equals(BigInteger.TEN)) 
      return " equal"; 
     else 
      return " different"; 
    } 
} 

と出力

Long before: 1 
    trickyMethod: 10 
    equal 
Long after: 1 

BigInteger before: 1 
    trickyMethod: 10 
    equal 
BigInteger after: 1 

POJOのデモ

public class Demo { 

    static class Container { 
     private Long l; 

     public Container(Long l) { 
      this.l = l; 
     } 

     @Override 
     public String toString() { 
      return String.valueOf(l); 
     } 

     @Override 
     public boolean equals(Object obj) { 
      Container c = (Container) obj; 
      return l.equals(c.l); 
     } 
    } 

    public static void main(String[] args) { 
     Container container = new Container(1L); 
     System.out.println("Container before: "+ container); 
     System.out.println(trickyMethod(container)); 
     System.out.println("Container after: " + container); 
    } 

    private static String trickyMethod(final Container container) { 
     container.l = 10L; 
     System.out.println(" trickyMethod: " + container); 

     if (container.equals(new Container(10L))) 
      return " equal"; 
     else 
      return " different"; 
    } 
} 

と出力

Container before: 1 
    trickyMethod: 10 
    equal 
Container after: 10 

開発者がLongの場合には、このString method(final Long value)のようなメソッドのシグネチャでは、最終的なキーワードを使用するのはなぜ?

+0

変数とパラメータの再利用(意味が変更されている)は、非常に多くの場合、わかりやすく、見つけにくいバグです。 'final'キーワードは、パラメータに新しい値を与えようとするとコンパイラエラーを引き起こします。また、内部的な理由から、そのメソッドで作成された匿名クラス内でパラメータが使用されている場合、パラメータは 'final'でなければなりません。 'trickyMethod'の –

+0

は、最終フィールドではない' container.l'を再割り当てしています。 'container'自体を再割り当てすると、コンパイラエラー – Vanguard

答えて

5

パラメータが不変であるかどうかはこれまでに問題ではありません。最終的な変更可能なパラメータは内部的に変更することができ、パラメータ変数に何かを再割り当てすることはできません。

Javaで無駄なものの1つは、パラメーターが暗黙的に最終的だった場合はいいでしょう。パラメーターを再割り当てする場合はコードの匂いです。ほとんどのコードアナライザは、これをバグ/警告/などとして報告します。

基本的なルールは、構文上、パラメータをfinalにする必要がある場合を除いて、コードに無駄な乱雑さをもたらすだけなので、パラメータをfinalにするのは苦労しないことです。ただし、バグの可能性があるため、パラメータの再割り当ては行わないでください。はすべてのパラメータが最終的なものです。

0

java.langパッケージラッパークラスはすべて不変です。これにはString、Long、Doubleなどが含まれます。したがって、最終的にマークしても問題はありません。しかし、あなたの例ではvalueの参照を再割り当てしていることに注意してください。たとえば、StringBuilderの場合は、新しいオブジェクト参照になります。

あなたが正しいですが、不変のオブジェクトの場合は問題ありません。

+2

*" java.langパッケージのすべてのラッパークラスは不変です "*メソッドパラメータに' final'を使うかどうかは関係ありません。 –

3

開発者が以下を使用する理由は、単に変数の再割り当てを防止するためです。だから、

例えば

void method(final long value){ 
    long number = 90; 
    value = number; // COMPILER ERROR 
} 

あなたが誤って、それはそれ悪い状況になります再割り当て、あなたが最終としてそれを宣言することができるときに、後でそれを再割り当てしたくない場合は、私は推測します。

+0

この場合ではありません。 –

+0

申し訳ありませんが、それを拡張できますか? –

+0

あなたが書いたものは本当です;)しかし、質問そのものはv。によって渡され、rによって渡されます。 –

関連する問題