java にはキーワードがあります -
final
。クラス、メソッド、変数 (メソッド引数を含む) に適用できます。 クラスの場合、これは、そのクラスがサブクラスを持つことができないことを意味します。継承は禁止されています。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 Classes
Anonymous 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 開発者になって、面白くて高収入の仕事に就くことです。 それでは、始めましょう。
-
配列が宣言されたとき、配列について何を言えますか
final
? -
クラスが
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 チームについて少し脱線しましょう。コンテンツを非表示にするブロックをテキスト エディタに追加し、それをクリックするとこのコンテンツが表示されるようにしてください。答え:
-
なぜなら 配列はオブジェクトです。つまり
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
-
はい、できます。重要なのは、物体に対するこの厄介な言葉の使い方を理解することです
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 を介してその値を変更してみてください。皆さんお元気で!
GO TO FULL VERSION