オブジェクトの作成時にクラスの最終変数をどのように初期化できるのでしょうか?
誰でもそれがどのように可能か説明できますか? ...
宣言時に初期化されない最終変数は、空の最終変数と呼ばれ、初期化する必要がありますon all constructor either explicitly or by calling this()
。そうしないと、コンパイラは次のように文句を言います"final variable (name) might not be initialized".
ウィキペディアによると
final 変数は、初期化子または割り当てステートメントを介して一度だけ初期化できます。宣言の時点で初期化する必要はありません。これは"blank final"
変数と呼ばれます。クラスの空の final インスタンス変数は、それが宣言されているクラスのすべてのコンストラクターの最後に確実に割り当てる必要があります。同様に、空白の final 静的変数は、それが宣言されているクラスの静的初期化子で確実に割り当てる必要があります。そうしないと、どちらの場合もコンパイル時エラーが発生します。
例えば。
public class Sphere {
// pi is a universal constant, about as constant as anything can be.
public static final double PI = 3.141592653589793;
public final double radius;
public final double xPos;
public final double yPos;
public final double zPos;
Sphere(double x, double y, double z, double r) {
radius = r;
xPos = x;
yPos = y;
zPos = z;
}
[...]
}
詳細については、wiki ページ http://en.wikipedia.org/wiki/Final_(Java)を参照してください。
これは、JVM が内部で動作する方法と Java の設計方法によって可能になります。
コードがコンパイルされた後、生成された .class ファイルには、コードのバイトコード表現が含まれます。クラスファイルは、定義された順序で構造化された一連のバイトであり、JVM によって解釈されます。
クラス ファイル構造では、定数プールと呼ばれるものを見つけることができます。これは、クラスがロードされるときに JVM によって使用されるシンボリック参照テーブルに他なりません。最終的な変数は、リテラルとして初期化されているかどうかにかかわらず、ここにあります。
これがわかったので、次に進んで final 修飾子の意味を考えてみましょう。これは、この場合変数に値が割り当てられ、これが完了すると再割り当てが行われることを JVM に伝える方法に他なりません。その変数に対する操作は許可されないため、Java 言語のドキュメントに記載されているように、最終的な変数には 1 回だけ値を割り当てることができます。
あなたの質問に直接答えるために、この背景を持っているので:
変数がオブジェクトまたはプリミティブ型のどちらであるかにかかわらず、クラス メンバーではない (つまり、静的ではない) final 変数の値は、オブジェクトのランタイム定数プールの値を使用して JVM によって自動的に設定されます。 variable は宣言時に初期化されないため、コンストラクターの実行時に設定する必要があります。これが可能なのは、Java がこのように設計されているためです。これは、ハードコーディングを回避し、オブジェクトを最終的な参照に割り当てる方法を提供するために、変数の割り当てに関してプログラマーにある程度の柔軟性を提供するためです。
最後のヒントとして、最終変数を C++ の定数と考えるのをやめてください。それらは似ているように見えるかもしれませんが、まったく異なる方法で処理されます。
はい、オブジェクトの作成時にクラスの最終変数を初期化できます。そうすると、毎回その最終インスタンス変数(最終静的変数ではない)の各オブジェクトに最終値が割り当てられますが、値が割り当てられるとオブジェクトに変更することはできません。
class Demo
{
public final int num;
public Demo(final int n)
{
this.num = n;// this will assign a final value for each object now
}
}
public class Sample
{ public static void main(String[] args)
{
Demo d = new Demo(20);
System.out.println(d.num);
Demo d1 = new Demo(21);
System.out.println(d1.num);
d1.num=22;//Invalid will give error now because you are trying to change the final value for d1 object
System.out.println(d1.num);
}
}
値は、コンストラクター内で一final
度だけ設定できる値です。コンストラクターが好きな値に設定できない理由はありません。
すべてのインスタンスの定数にしたい値がある場合、それを作成static final
し、コンストラクターで設定することはできません。おそらく、あなたは2つを混同しています。
なぜだめですか。このような
public class GenericFoo{
final int var;
GenericFoo(){
var = 100;
}
}
コンストラクターが完了する前に、最終的なインスタンス変数を初期化できます。JSL
によると
空白の final インスタンス変数は、それが宣言されているクラスのすべてのコンストラクターの最後に確実に割り当てる必要があります。そうしないと、コンパイル時エラーが発生します。
Javaの空白の最終変数は、宣言中に初期化されない最終変数です
したがって、それを行うには2つの方法があります。
方法1:コンストラクターで
class Program {
final int i3;
Program() {
i3 = 10;
}
}
方法 2: インスタンス ブロック内
class Program {
final int i3;
{
i3 = 10;
}
}