117

块内初始化有什么区别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;

    ....
4

13 回答 13

129

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

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
}
于 2012-02-21T14:41:26.270 回答
20

您可以在内部使用 try/catch 块,static{}如下所示:

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:参考于此

于 2018-07-13T01:37:10.850 回答
19

一个典型的用法:

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

static {
    SET.add("value1");
    SET.add("value2");
    SET.add("value3");
}

如果没有静态初始化器,你会怎么做?

于 2012-02-21T14:45:15.803 回答
12

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

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

这对于像上面那样烦人地抛出检查异常的构造函数或可能容易出现异常的更复杂的初始化逻辑很有用。

于 2012-02-21T14:47:36.287 回答
7

我们使用构造函数有条件地初始化我们的实例变量。

如果你想有条件地初始化类/静态变量,并且想在不创建对象的情况下进行(构造函数只能在创建对象时调用),那么你需要静态块。

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);
    }
}
于 2018-04-03T22:09:40.943 回答
5

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

于 2012-02-21T14:41:23.133 回答
4

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

于 2012-02-21T14:40:57.880 回答
4

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

于 2012-02-22T08:35:40.337 回答
3

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

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

于 2012-02-21T14:42:14.300 回答
3

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

举个例子,有一个鞋类,其中有几个变量,如颜色、尺寸、品牌等……如果鞋类制造公司只有一个品牌,我们应该将其初始化为静态变量。因此,当调用鞋类并制造不同类型的鞋(通过创建类的实例)时,每当创建新鞋时颜色和尺寸都会占用内存,但这里品牌是所有鞋的共同属性,这样无论生产多少鞋,它都会占用一次内存。

例子:

    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("=================");
    }
}
于 2016-08-24T12:09:52.080 回答
1

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

进一步来说,

static final String ab = a+b;
static final String a = "Hello,";
static final String b = ", world";

将不起作用,因为 a 和 b 是在 ab 之后声明的。

但是我可以使用静态初始化。块来克服这一点。

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;
}
于 2012-02-21T14:46:32.880 回答
0

如果您希望在第一次使用类之前初始化指定的类静态类型,则静态初始化块很有用。后续使用不会调用任何静态初始化块。它与初始化实例成员的实例初始化器正好相反。

于 2017-10-12T05:14:43.140 回答
0

当您想在类加载时评估任何特定表达式时,您可以使用静态块,但请记住:

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

于 2019-08-19T13:45:12.027 回答