JavaRush /Java Blog /Random-JA /ということで最後に…
Алексей
レベル 32

ということで最後に…

Random-JA グループに公開済み
java にはキーワードがあります - final。クラス、メソッド、変数 (メソッド引数を含む) に適用できます。 では最後に... - 1クラスの場合、これは、そのクラスがサブクラスを持つことができないことを意味します。継承は禁止されています。immutableこれは、 (不変) オブジェクト (たとえば、Stringとして宣言されたクラス)を作成するときに便利ですfinal

    public final class String{
    }
    
    class SubString extends String{ //Compilation error
    }
また、修飾子は抽象クラス (キーワード を使用abstract)には適用できないことfinalにも注意してください。これらは相互に排他的な概念です。メソッドの場合、finalサブクラスでオーバーライドできないことを意味します。これは、元の実装をオーバーライドしたくない場合に便利です。

    public class SuperClass{
        public final void printReport(){
            System.out.println("Report");
        }
    }

    class SubClass extends SuperClass{ 
        public void printReport(){  //Compilation error
            System.out.println("MyReport");
        }
    }
プリミティブ型変数の場合、これは、一度割り当てられると値を変更できないことを意味します。参照変数の場合、これは、オブジェクトが割り当てられると、そのオブジェクトへの参照を変更できないことを意味します。大事です!リンクは変更できませんが、オブジェクトの状態は変更できます。Java 8 では、この概念が登場しましたeffectively final。これは変数 (メソッド引数を含む) にのみ適用されます。重要なのは、キーワードが明らかに存在しないにもかかわらずfinal、変数の値は初期化後に変更されないということです。つまり、finalコンパイル エラーを発生させることなく、そのような変数を単語に置き換えることができます。変数は、ローカル クラス ( )、匿名クラス ( )、ストリーム (Stream API) effectively final内で使用できます。Local Inner ClassesAnonymous Inner Classes

        public void someMethod(){
            // In the example below, both a and b are effectively final, since the values ​​are set once:
            int a = 1;
            int b;
            if (a == 2) b = 3;
            else b = 4;
            // c is NOT effectively final because value changes
            int c = 10;
            c++;
            
            Stream.of(1, 2).forEach(s-> System.out.println(s + a)); //Ок
            Stream.of(1, 2).forEach(s-> System.out.println(s + c)); //Compilation error
        }
それでは、少しインタビューをしてみましょう。結局のところ、JavaRush コースを受講する目標は、Java 開発者になって、面白くて高収入の仕事に就くことです。 それでは、始めましょう。
  1. 配列が宣言されたとき、配列について何を言えますかfinal?

  2. クラスがStringであることimmutable、クラスが宣言されていることfinal、文字列の値がキーワードcharでマークされた配列に格納されていることはわかっていますfinal


public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
String(オブジェクトへの参照を変更せずに) オブジェクトの値を置き換えることはできますか? これらは実際の面接の質問です。実際にやってみるとわかるように、多くの人が間違って答えます。キーワードの使用法final、特に参照変数の使用法を理解することは非常に重要です。考えている間に、JavaRush チームについて少し脱線しましょう。コンテンツを非表示にするブロックをテキスト エディタに追加し、それをクリックするとこのコンテンツが表示されるようにしてください。答え:
  1. なぜなら 配列はオブジェクトです。つまりfinal、オブジェクトに参照を割り当てた後は変更できませんが、オブジェクトの状態は変更できます。

    
            final int[] array = {1,2,3,4,5};
            array[0] = 9;	//ok, because change the contents of the array - {9,2,3,4,5}
            array = new int[5]; //compile error
  2. はい、できます。重要なのは、物体に対するこの厄介な言葉の使い方を理解することですfinal。ReflectionAPI を使用して値を置き換えます。


import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        //Get the value field in the String class
        Field field = value.getClass().getDeclaredField("value");
        //Let's change it
        field.setAccessible(true);
        //Set new value
        field.set(value, "JavaRush".toCharArray());

        System.out.println(value);

        /* Вывод:
         * Old value
         * JavaRush
         */
    }
}
この方法でプリミティブ型の最終変数を変更しようとしても、何も機能しないことに注意してください。これを自分自身に納得させることをお勧めします。たとえば、final intフィールドを含む Java クラスを作成し、Reflection API を介してその値を変更してみてください。皆さんお元気で!
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION