静态块也被称为静态初始化块。静态初始化块是以 static 关键字开头并用大括号括起来的正常的代码块 。下面是一个例子:
static {
// whatever code is needed for initialization goes here
}
静态块在 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");
}
}
以上代码的输出结果:
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” 关键字,那么这个块被称为“构造块”,并且在类每次被实例化时都将被执行。构造函数块将被复制到类的每个构造函数中。例如,我们有四个参数化的构造函数,那么四个构造块的副本将被放置在构造函数中,每个构造函数一个。让我们执行下面的例子,看看输出:
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");
}
}
上面的代码的输出结果:
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
我们应该用私有静态方法去初始化公有的静态变量:
class Whatever {
private varType myVar = initializeInstanceVariable();
protected final varType initializeInstanceVariable() {
// initialization code goes here
}
}
私有静态方法的优点是,如果需要重新初始化公有的静态变量,可以更加灵活地重用私有静态方法。因此,与相应的静态初始化块相比,我们可以通过私有静态方法获得更大的灵活性。我们不是说公有的静态方法不能做到这一点。 只是,我们正在谈论一种初始化类变量的方法,几乎没有任何理由使这种初始化的方法“公开”。
那么静态块的优点是什么?
- 如果我们正在加载驱动程序和其他项目到命名空间。例如,Class类有一个静态块,它注册了本机。
- 如果我们需要执行计算来初始化您的静态变量,那么您可以声明一个静态块,该类在第一次加载时才会被执行一次。
- 与安全相关的问题或与日志记录相关
当然静态块也有局限性
- JVM 的一个限制是静态初始化块不应该超过 64K
- 不能抛出检查异常
- 不能使用 this 关键字,因为还没有其实例
- 不应该尝试访问 super,因为对静态块来说没有这样 super
- 不应该从这个块返回任何东西
- 静态块可能会使测试成为一场噩梦
最后如何处理静态块中的异常?
在方法中,可以通过异常处理或处理异常来处理异常。但是在静态块代码中,你不能以这种方式处理异常。
通常一个干净利落的方式来处理它是使用 try-catch 块,但在静态块代码中,因为我们没有这个选项,因此让我们看看可用的三个选项:
首先在记录异常之后抛出一个 RuntimeException,它将结束当前线程(除非被代码初次实例化或者在类上第一次调用静态方法)。
其次是调用 System.exit(1),但是这在像 servlet 这样的托管环境中是不可取的。此选项仅适用于 Java 应用程序,并且只有在静态初始化块执行一些关键操作(没有这些关键操作,程序无法成功运行)的情况下,才能加载数据库驱动程序。
最后一个选项是设置一个标志指示失败。稍后,构造函数可以检查标志并在需要的情况下抛出异常或重试。
最后,如果操作对程序的功能不重要,那么可能只需要一个简单的日志。
静态块 在 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);
}
}
上面的代码的输出结果:
本文参考链接:
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