コードをコンストラクター、メソッド、または初期化ブロックに配置できます。初期化ブロックの使用は何ですか?すべてのJavaプログラムがそれを持たなければならないのですか?
まず、2つのタイプの 初期化ブロック があります。
このコードは、それらの使用方法と実行順序を示しているはずです。
public class Test {
static int staticVariable;
int nonStaticVariable;
// Static initialization block:
// Runs once (when the class is initialized)
static {
System.out.println("Static initalization.");
staticVariable = 5;
}
// Instance initialization block:
// Runs each time you instantiate an object
{
System.out.println("Instance initialization.");
nonStaticVariable = 7;
}
public Test() {
System.out.println("Constructor.");
}
public static void main(String[] args) {
new Test();
new Test();
}
}
プリント:
Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.
インスタンスの初期化ブロックは、使用するコンストラクターに関係なくコードを実行したい場合、または匿名クラスのインスタンスを初期化したい場合に役立ちます。
@aioobeの答えに追加したい
実行順序:
スーパークラスの静的初期化ブロック
クラスの静的初期化ブロック
スーパークラスのインスタンス初期化ブロック
スーパークラスのコンストラクター
クラスのインスタンス初期化ブロック
クラスのコンストラクタ。
留意すべき追加のポイントがいくつかあります(ポイント1は@aioobeの回答の繰り返しです)。
静的初期化ブロックのコードは、クラスのロード時に(そして、クラスのロードごとに1回だけ実行されることを意味します)、クラスのインスタンスが構築される前、および静的メソッドが呼び出される前に実行されます。
インスタンス初期化ブロックは、実際にはJavaコンパイラーによってクラスが持つすべてのコンストラクターにコピーされます。したがって、インスタンス初期化ブロックのコードが実行されるたびにexactlyコンストラクタ。
さらにいくつかのポイントを追加するaioobeによる素敵な答え
public class StaticTest extends parent {
static {
System.out.println("inside satic block");
}
StaticTest() {
System.out.println("inside constructor of child");
}
{
System.out.println("inside initialization block");
}
public static void main(String[] args) {
new StaticTest();
new StaticTest();
System.out.println("inside main");
}
}
class parent {
static {
System.out.println("inside parent Static block");
}
{
System.out.println("inside parent initialisation block");
}
parent() {
System.out.println("inside parent constructor");
}
}
これは与える
inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main
明らかなことを述べるようなものですが、もう少し明確に見えます。
ここでの回答として承認されているサンプルコードは正しいですが、私は同意しません。何が起こっているのかは示していませんが、実際にJVMがどのように機能するかを理解するための良い例を示します。
package test;
class A {
A() {
print();
}
void print() {
System.out.println("A");
}
}
class B extends A {
static int staticVariable2 = 123456;
static int staticVariable;
static
{
System.out.println(staticVariable2);
System.out.println("Static Initialization block");
staticVariable = Math.round(3.5f);
}
int instanceVariable;
{
System.out.println("Initialization block");
instanceVariable = Math.round(3.5f);
staticVariable = Math.round(3.5f);
}
B() {
System.out.println("Constructor");
}
public static void main(String[] args) {
A a = new B();
a.print();
System.out.println("main");
}
void print() {
System.out.println(instanceVariable);
}
static void somethingElse() {
System.out.println("Static method");
}
}
ソースコードについてコメントする前に、クラスの静的変数について簡単に説明します。
まず最初に、それらはクラス変数と呼ばれ、クラスの特定のインスタンスではなくクラスに属します。クラスのすべてのインスタンスは、このstatic(class)変数を共有します。各変数には、プリミティブ型または参照型に応じてデフォルト値があります。別のことは、クラスの一部のメンバー(初期化ブロック、コンストラクター、メソッド、プロパティ)で静的変数を再割り当てし、特定のインスタンスではなく静的変数の値を変更することです。インスタンス。静的部分を結論付けるために、クラスの静的変数は、クラスを初めてインスタンス化するときではなく、クラスを定義するときに作成され、インスタンスを必要とせずにJVMに存在すると言います。そのため、外部クラス(定義されていないクラス)からの静的メンバーへの正しいアクセスは、ドットに続くクラス名を使用し、次にアクセスする静的メンバー(テンプレート:<CLASS_NAME>.<STATIC_VARIABLE_NAME>
)。
それでは、上記のコードを見てみましょう。
エントリポイントが主な方法です。コードは3行だけです。現在承認されている例を参照します。それによると、「静的初期化ブロック」を印刷した後に最初に印刷する必要があるのは「初期化ブロック」であり、これは私の不一致です。非静的初期化ブロックはコンストラクターの前に呼び出されず、コンストラクターの初期化の前に呼び出されます初期化ブロックが定義されているクラスのクラスのコンストラクターは、オブジェクト(クラスのインスタンス)を作成するときに最初に関与し、コンストラクターに入るときに最初に呼び出される部分は、暗黙的な(デフォルトの)スーパーコンストラクターまたは明示的なスーパーコンストラクターまたは別のオーバーロードの明示的な呼び出しですコンストラクター(ただし、オーバーロードされたコンストラクターのチェーンがある場合は、最後のコンストラクターが暗黙的または明示的にスーパーコンストラクターを呼び出します)。
オブジェクトのポリモーフィックな作成がありますが、クラスBとそのメインメソッドに入る前に、JVMはすべてのクラス(静的)変数を初期化し、存在する場合は静的初期化ブロックを通過してからクラスBに入り、 mainメソッドの実行。クラスBのコンストラクターに移動し、クラスAのコンストラクターの本体で呼び出されるメソッド(オーバーライドメソッド)がクラスBで定義されているメソッドであるポリモーフィズムを使用して、クラスAのコンストラクターを直ちに(暗黙的に)呼び出しますinstanceVariableという名前の変数は、再初期化の前に使用されます。クラスBのコンストラクターを閉じた後、スレッドはクラスBのコンストラクターに返されますが、「コンストラクター」を出力する前に非静的初期化ブロックに最初に行きます。いくつかのIDEでデバッグをよりよく理解するために、Eclipseを好みます。
Initializerブロックには、インスタンスが作成されるたびに常に実行されるコードが含まれています。クラスのさまざまなコンストラクターの共通部分を宣言/初期化するために使用されます。
初期化コンストラクターと初期化ブロックの順序は関係ありません。初期化ブロックは常にコンストラクターの前に実行されます。
クラスのすべてのオブジェクトに対してコードを1回実行する場合はどうなりますか?
Javaで静的ブロックを使用します。
初期化ブロックは、クラスが初期化されるたびに、コンストラクターが呼び出される前に実行されます。これらは通常、中括弧内のコンストラクターの上に配置されます。それらをクラスに含める必要はまったくありません。
これらは通常、参照変数を初期化するために使用されます。この page は良い説明を与えます
初期化<abbr>
要素内のテキストをわずかに小さいフォントサイズで表示します
問題は完全に明確ではありませんが、オブジェクトのデータを初期化する方法の簡単な説明を以下に示します。オブジェクトのリストを保持するクラスAがあるとします。
1)フィールド宣言に初期値を入れます:
class A {
private List<Object> data = new ArrayList<Object>();
}
2)コンストラクターで初期値を割り当てます。
class A {
private List<Object> data;
public A() {
data = new ArrayList<Object>();
}
}
これらは両方とも、コンストラクタ引数として「データ」を渡したくないことを前提としています。
上記のようなオーバーロードされたコンストラクターと内部データを混在させると、事態は少し複雑になります。考慮してください:
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
data = new ArrayList<Object>();
name = "Default name";
userFriendlyName = "Default user friendly name";
}
public B(String name) {
data = new ArrayList<Object>();
this.name = name;
userFriendlyName = name;
}
public B(String name, String userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
繰り返しコードがたくさんあることに注意してください。これを解決するには、コンストラクターが相互に呼び出すようにするか、各コンストラクターが呼び出すプライベートな初期化メソッドを使用します。
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
this("Default name", "Default user friendly name");
}
public B(String name) {
this(name, name);
}
public B(String name, String userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
または
class B {
private List<Object> data;
private String name;
private String userFriendlyName;
public B() {
init("Default name", "Default user friendly name");
}
public B(String name) {
init(name, name);
}
public B(String name, String userFriendlyName) {
init(name, userFriendlyName);
}
private void init(String _name, String _userFriendlyName) {
data = new ArrayList<Object>();
this.name = name;
this.userFriendlyName = userFriendlyName;
}
}
2つは(ほぼ)同等です。
これで、オブジェクトのデータを初期化する方法についてのヒントが得られることを願っています。静的初期化ブロックについては、現時点では少し進んでいる可能性があるため、説明しません。
編集:初期化ブロックは比較的高度な概念であるため、「初期化ブロックがどのように機能するか」ではなく「インスタンス変数を初期化する方法」としてあなたの質問を解釈しました、そして質問のトーンからあなたが尋ねているようですよりシンプルなコンセプト。私は間違っている可能性があります。
public class StaticInitializationBlock {
static int staticVariable;
int instanceVariable;
// Static Initialization Block
static {
System.out.println("Static block");
staticVariable = 5;
}
// Instance Initialization Block
{
instanceVariable = 7;
System.out.println("Instance Block");
System.out.println(staticVariable);
System.out.println(instanceVariable);
staticVariable = 10;
}
public StaticInitializationBlock() {
System.out.println("Constructor");
}
public static void main(String[] args) {
new StaticInitializationBlock();
new StaticInitializationBlock();
}
}
出力:
Static block
Instance Block
5
7
Constructor
Instance Block
10
7
Constructor