靜態(tài)塊也被稱為靜態(tài)初始化塊。靜態(tài)初始化塊是以 static 關(guān)鍵字開頭并用大括號括起來的正常的代碼塊 。下面是一個例子:
static {
// whatever code is needed for initialization goes here
}
靜態(tài)塊在 Java 中的使用實例:
public class StaticExample{
static {
System.out.println("This is first static block");
}
public StaticExample(){
System.out.println("This is constructor");
}
public static String staticString = "Static Variable";
static {
System.out.println("This is second static block and "
+ staticString);
}
public static void main(String[] args){
StaticExample statEx = new StaticExample();
StaticExample.staticMethod2();
}
static {
staticMethod();
System.out.println("This is third static block");
}
public static void staticMethod() {
System.out.println("This is static method");
}
public static void staticMethod2() {
System.out.println("This is static method2");
}
}
以上代碼的輸出結(jié)果:
This is first static block
This is second static block and Static Variable
This is static method
This is third static block
This is constructor
This is static method2
如果代碼塊前面不加 “static” 關(guān)鍵字,那么這個塊被稱為“構(gòu)造塊”,并且在類每次被實例化時都將被執(zhí)行。構(gòu)造函數(shù)塊將被復(fù)制到類的每個構(gòu)造函數(shù)中。例如,我們有四個參數(shù)化的構(gòu)造函數(shù),那么四個構(gòu)造塊的副本將被放置在構(gòu)造函數(shù)中,每個構(gòu)造函數(shù)一個。讓我們執(zhí)行下面的例子,看看輸出:
public class ConstructorBlockExample{
{
System.out.println("This is first constructor block");
}
public ConstructorBlockExample(){
System.out.println("This is no parameter constructor");
}
public ConstructorBlockExample(String param1){
System.out.println("This is single parameter constructor");
}
public ConstructorBlockExample(String param1, String param2){
System.out.println("This is two parameters constructor");
}
{
System.out.println("This is second constructor block");
}
public static void main(String[] args){
ConstructorBlockExample constrBlockEx =
new ConstructorBlockExample();
ConstructorBlockExample constrBlockEx1 =
new ConstructorBlockExample("param1");
ConstructorBlockExample constrBlockEx2 =
new ConstructorBlockExample("param1", "param2");
}
}
上面的代碼的輸出結(jié)果:
This is first constructor block
This is second constructor block
This is no parameter constructor
This is first constructor block
This is second constructor block
This is single parameter constructor
This is first constructor block
This is second constructor block
This is two parameters constructor
我們應(yīng)該用私有靜態(tài)方法去初始化公有的靜態(tài)變量:
class Whatever {
private varType myVar = initializeInstanceVariable();
protected final varType initializeInstanceVariable() {
// initialization code goes here
}
}
私有靜態(tài)方法的優(yōu)點是,如果需要重新初始化公有的靜態(tài)變量,可以更加靈活地重用私有靜態(tài)方法。因此,與相應(yīng)的靜態(tài)初始化塊相比,我們可以通過私有靜態(tài)方法獲得更大的靈活性。我們不是說公有的靜態(tài)方法不能做到這一點。 只是,我們正在談?wù)撘环N初始化類變量的方法,幾乎沒有任何理由使這種初始化的方法“公開”。
那么靜態(tài)塊的優(yōu)點是什么?
- 如果我們正在加載驅(qū)動程序和其他項目到命名空間。例如,Class類有一個靜態(tài)塊,它注冊了本機。
- 如果我們需要執(zhí)行計算來初始化您的靜態(tài)變量,那么您可以聲明一個靜態(tài)塊,該類在第一次加載時才會被執(zhí)行一次。
- 與安全相關(guān)的問題或與日志記錄相關(guān)
當(dāng)然靜態(tài)塊也有局限性
- JVM 的一個限制是靜態(tài)初始化塊不應(yīng)該超過 64K
- 不能拋出檢查異常
- 不能使用 this 關(guān)鍵字,因為還沒有其實例
- 不應(yīng)該嘗試訪問 super,因為對靜態(tài)塊來說沒有這樣 super
- 不應(yīng)該從這個塊返回任何東西
- 靜態(tài)塊可能會使測試成為一場噩夢
最后如何處理靜態(tài)塊中的異常?
在方法中,可以通過異常處理或處理異常來處理異常。但是在靜態(tài)塊代碼中,你不能以這種方式處理異常。
通常一個干凈利落的方式來處理它是使用 try-catch 塊,但在靜態(tài)塊代碼中,因為我們沒有這個選項,因此讓我們看看可用的三個選項:
首先在記錄異常之后拋出一個 RuntimeException,它將結(jié)束當(dāng)前線程(除非被代碼初次實例化或者在類上第一次調(diào)用靜態(tài)方法)。
其次是調(diào)用 System.exit(1),但是這在像 servlet 這樣的托管環(huán)境中是不可取的。此選項僅適用于 Java 應(yīng)用程序,并且只有在靜態(tài)初始化塊執(zhí)行一些關(guān)鍵操作(沒有這些關(guān)鍵操作,程序無法成功運行)的情況下,才能加載數(shù)據(jù)庫驅(qū)動程序。
最后一個選項是設(shè)置一個標(biāo)志指示失敗。稍后,構(gòu)造函數(shù)可以檢查標(biāo)志并在需要的情況下拋出異?;蛑卦嚒?/p>
最后,如果操作對程序的功能不重要,那么可能只需要一個簡單的日志。
靜態(tài)塊 在 Android 中的使用實例
代碼如下:
package com.toby.test_application;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
private static final String TAG = "Test_MainActivity";
private static IntentFilter s_intentFilter;
private static List<String> s_stringList;
static {
s_intentFilter = new IntentFilter();
s_intentFilter.addAction(Intent.ACTION_TIME_TICK);
s_intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
s_intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
s_stringList = new ArrayList<>();
s_stringList.add("one");
s_stringList.add("two");
s_stringList.add("three");
s_stringList.add("four");
}
private final BroadcastReceiver m_testReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_TIME_CHANGED) ||
action.equals(Intent.ACTION_TIMEZONE_CHANGED))
{
// TODO: 17-11-14 something
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(m_testReceiver, s_intentFilter);
Log.d(TAG, "s_intentFilter hasAction ACTION_TIME_TICK: "
+ s_intentFilter.hasAction(Intent.ACTION_TIME_TICK));
Log.d(TAG, "s_intentFilter hasAction ACTION_TIMEZONE_CHANGED: "
+ s_intentFilter.hasAction(Intent.ACTION_TIMEZONE_CHANGED));
Log.d(TAG, "s_intentFilter hasAction ACTION_TIME_CHANGED: "
+ s_intentFilter.hasAction(Intent.ACTION_TIME_CHANGED));
Log.d(TAG, s_stringList.toString());
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(m_testReceiver);
}
}
上面的代碼的輸出結(jié)果:

本文參考鏈接:
http://java2novice.com/java-fundamentals/static/block/
http://jusfortechies.com/java/core-java/static-blocks.php
https://stackoverflow.com/questions/5481386/date-and-time-change-listener-in-android