Java:静态初始化块什么时候有用?

Java:静态初始化块什么时候有用?,java,static-initialization,Java,Static Initialization,静态块中的初始化之间有什么区别: 公共类静态测试{ 静态字符串s; 静态int n; 静态双d; 静止的{ s=“我是静态的”; n=500; d=4000.0001; } ... 和单个静态初始化: 公共类静态测试{ 静态字符串s=“我是静态的”; 静态int n=500; 静态双d=4000.0001; .... 在您的示例中,没有区别;但初始值通常比用单个表达式轻松表达更复杂(例如,它是一个列表,其内容最好用for-循环表示;或者它是一个可能不存在的方法,因此需要异常处理程序),和/或静

静态
块中的初始化之间有什么区别:

公共类静态测试{
静态字符串s;
静态int n;
静态双d;
静止的{
s=“我是静态的”;
n=500;
d=4000.0001;
}
...
和单个静态初始化:

公共类静态测试{
静态字符串s=“我是静态的”;
静态int n=500;
静态双d=4000.0001;
....

在您的示例中,没有区别;但初始值通常比用单个表达式轻松表达更复杂(例如,它是一个
列表
,其内容最好用
for
-循环表示;或者它是一个可能不存在的
方法
,因此需要异常处理程序),和/或静态字段需要按特定顺序设置。

有时,您需要做的不仅仅是为静态变量赋值。由于您不能在类体中放入任意语句,因此可以使用静态初始化程序块。

静态初始化程序块允许更复杂的初始化,例如使用条件变量s:

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
}

从技术上讲,你可以不用它。有些人喜欢多行初始化代码进入静态方法。我很高兴使用静态初始化器进行相对简单的多语句初始化

当然,我几乎总是将静态设置为final,并指向一个不可修改的对象。

一个典型用法:

private final static Set<String> SET = new HashSet<String>();

static {
    SET.add("value1");
    SET.add("value2");
    SET.add("value3");
}
private final static Set=new HashSet();
静止的{
设置。添加(“值1”);
设置。添加(“价值2”);
设置。添加(“值3”);
}

如果没有静态初始值设定项,您将如何执行此操作?

静态代码块允许使用多个指令初始化字段,以不同的声明顺序初始化字段,还可以用于条件初始化

更具体地说

static final String ab = a+b;
static final String a = "Hello,";
static final String b = ", world";
将不起作用,因为a和b在ab之后声明

但是,我可以使用静态init.block来克服这个问题

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;
}

初始化期间的异常处理是另一个原因。例如:

static URL url;
static {
    try {
        url = new URL("https://blahblah.com");
    }
    catch (MalformedURLException mue) {
        //log exception or handle otherwise
    }
}

这对于那些烦人地抛出检查过的异常(如上面所述)或更复杂的初始化逻辑(可能容易发生异常)的构造函数非常有用。

static
块可用于初始化singleton实例,以防止使用synchronized
getInstance()
方法。

静态关键字(无论是变量还是块)是属于该类的。因此,当调用该类时,将执行这些变量或块。因此,大多数初始化都将在static关键字的帮助下完成。由于它属于该类本身,该类可以直接访问它,而无需创建该类的实例

让我们举个例子,有一个鞋类 几个变量,如颜色、尺寸、品牌等。这里是鞋子 制造公司只有一个品牌,我们不应该把它初始化为一个品牌 静态变量。因此,当调用shoe类时 通过创建类的实例,在 每当新鞋问世时,颜色和尺码都会占据人们的记忆 但在这里,品牌是所有鞋子的共同财产,因此 无论生产多少双鞋,都要占用内存一次

示例:

    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 = " + widht * height);
    }
}
静态扫描仪输入=新扫描仪(系统输入);
静态整数宽度;
静态内高度;
静止的
{
widt=input.nextInt();
input.nextLine();
高度=输入。nextInt();
input.close();
如果((宽<0)| |(高<0))
{
System.out.println(“java.lang.Exception:宽度和高度必须为正”);
}
其他的
{
System.out.println(“宽*高=+宽*高);
}
}

您可以在
静态{}
中使用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);
        }

    }
}
MyCode{
静态扫描仪输入=新扫描仪(System.in);
静态布尔标志=true;
static int B=input.nextInt();
static int H=input.nextInt();
静止的{
试一试{

如果(B当您想在类加载时计算任何特定表达式,那么您可以使用静态块,但请记住:

您必须在静态块中处理异常,这意味着您不能从静态块抛出异常


您只在静态初始化块中使用赋值,因此当然可以使用静态变量赋值。您是否尝试过查看如果需要执行非赋值语句会发生什么情况?这是加载类或加载本机库的好地方。请注意,应避免使用静态变量,因此应使用静态初始值通常情况下,初始化块不是一个好主意。如果您发现自己经常使用它们,那么可能会遇到一些麻烦。虽然您所说的是正确的,但它并没有证明静态初始化块的必要性。您可以将
ab
声明移到声明下方