static
ブロック内の初期化の違いは何ですか:
public class staticTest {
static String s;
static int n;
static double d;
static {
s = "I'm static";
n = 500;
d = 4000.0001;
}
...
そして、個々の静的初期化:
public class staticTest {
static String s = "I'm static";
static int n = 500;
static double d = 4000.0001;
....
静的初期化ブロックを使用すると、たとえば条件を使用して、より複雑な初期化を行うことができます。
static double a;
static {
if (SomeCondition) {
a = 0;
} else {
a = 1;
}
}
または、単なる構築以上のものが必要な場合:ビルダーを使用してインスタンスを作成する場合、静的フィールドの作成以外の例外処理または作業が必要です。
静的初期化ブロックは、インライン静的初期化子の後にも実行されるため、次のことが有効です。
static double a;
static double b = 1;
static {
a = b * 4; // Evaluates to 4
}
典型的な使用法:
private final static Set<String> SET = new HashSet<String>();
static {
SET.add("value1");
SET.add("value2");
SET.add("value3");
}
静的イニシャライザなしでどうしますか?
初期化中の例外処理も別の理由です。例えば:
static URL url;
static {
try {
url = new URL("https://blahblah.com");
}
catch (MalformedURLException mue) {
//log exception or handle otherwise
}
}
これは、上記のような迷惑なチェック例外をスローするコンストラクター、または例外が発生しやすい複雑な初期化ロジックに役立ちます。
以下のようにstatic{}
内でtry/catchブロックを使用できます。
MyCode{
static Scanner input = new Scanner(System.in);
static boolean flag = true;
static int B = input.nextInt();
static int H = input.nextInt();
static{
try{
if(B <= 0 || H <= 0){
flag = false;
throw new Exception("Breadth and height must be positive");
}
}catch(Exception e){
System.out.println(e);
}
}
}
PS: this !から参照
静的変数に値を割り当てるだけでなく、それ以上のことをしたい場合があります。クラス本体に任意のステートメントを入れることはできないため、静的初期化ブロックを使用できます。
static
ブロックを使用してsingletonインスタンスを初期化し、synchronizedgetInstance()
メソッドを使用しないようにすることができます。
あなたの例では、違いはありません。しかし、多くの場合、初期値は単一の式で快適に表現されるよりも複雑です(たとえば、List<String>
その内容はfor
-ループで最もよく表現されます。または、存在しない可能性があるMethod
であるため、例外ハンドラが必要です)、および/または静的フィールドを特定の順序で設定する必要があります。
技術的には、それなしで逃げることができます。静的メソッドに入るために、複数行の初期化コードを好む人もいます。比較的単純な複数ステートメントの初期化に静的初期化子を使用することは非常にうれしいです。
もちろん、私はほとんど常に静的final
を作成し、変更不可能なオブジェクトを指します。
静的キーワード(変数またはブロック)は、クラスに属します。そのため、クラスが呼び出されると、これらの変数またはブロックが実行されます。そのため、初期化のほとんどは、静的キーワードを使用して行われます。クラス自体に属しているため、クラスのインスタンスを作成せずに、クラスから直接アクセスできます。
たとえば、色、サイズ、ブランドなどのいくつかの変数がある靴のクラスがあります。そして、ここで靴製造会社がブランドを1つだけ持っている場合、静的変数として初期化する必要があります。そのため、その時点で靴クラスが呼び出され、さまざまな種類の靴が製造されると(クラスのインスタンスを作成することにより)、新しい靴が作成されるたびに色とサイズがメモリを占有しますが、ここではブランドはすべての靴に共通のプロパティです。いくつの靴が製造されても、一度だけメモリを占有します。
例:
class Shoe {
int size;
String colour;
static String brand = "Nike";
public Shoe(int size, String colour) {
super();
this.size = size;
this.colour = colour;
}
void displayShoe() {
System.out.printf("%-2d %-8s %s %n",size,colour, brand);
}
public static void main(String args[]) {
Shoe s1 = new Shoe(7, "Blue");
Shoe s2 = new Shoe(8, "White");
System.out.println("=================");
s1.displayShoe();
s2.displayShoe();
System.out.println("=================");
}
}
クラスのロード時に特定の式を評価する場合は、静的ブロックを使用できますが、覚えておいてください:
静的ブロックで例外を処理する必要があります。つまり、静的ブロックから例外をスローすることはできません。
静的初期化ブロックは、クラスを最初に使用する前に、指定したクラスの静的型を初期化する場合に役立ちます。その後の使用では、静的初期化ブロックは呼び出されません。インスタンスメンバーを初期化するインスタンス初期化子とは正反対です。
コンストラクターを使用して、インスタンス変数(非静的変数、クラスではなくオブジェクトに属する変数)を初期化します。
クラス変数(静的変数)を初期化し、オブジェクトを作成せずに初期化したい場合(コンストラクターはオブジェクトの作成時にのみ呼び出すことができます)、静的ブロックが必要です。
static Scanner input = new Scanner(System.in);
static int widht;
static int height;
static
{
widht = input.nextInt();
input.nextLine();
height = input.nextInt();
input.close();
if ((widht < 0) || (height < 0))
{
System.out.println("Java.lang.Exception: Width and height must be positive");
}
else
{
System.out.println("widht * height");
}
}
静的コードブロックにより、フィールドをinstuction以上で初期化し、宣言の異なる順序でフィールドを初期化でき、条件付き初期化にも使用できます。
すなわち、
static final String ab = a+b;
static final String a = "Hello,";
static final String b = ", world";
aとbはabの後に宣言されているため機能しません。
ただし、静的initを使用できます。これを克服するためにブロックします。
static final String ab;
static final String a;
static final String b;
static {
b = ", world";
a = "Hello";
ab = a + b;
}
static final String ab;
static final String a;
static final String b;
static {
b = (...) ? ", world" : ", universe";
a = "Hello";
ab = a + b;
}