Java中静态块的必要性 [英] Necessity of static block in Java

查看:105
本文介绍了Java中静态块的必要性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现在Java中,有一个名为 static block 的功能,其中包含首次加载类时执行的代码(我不明白是什么'加载'意味着,是否意味着初始化?)。有没有理由在静态块内而不是在构造函数中执行初始化位?我的意思是,即使构造函数做同样的事情,在第一次初始化类时也要做所有必要的事情。什么是静态块完成哪些构造函数不能?

I found that in Java, there is a feature called static block, which includes code that is executed when a class is first loaded (I don't understand what 'loaded' means, does it mean initialized?). Is there any reason to do the initialization bit inside a static block and not in the constructor? I mean, even the constructor does the same thing, do all the necessary stuff when a class is first initialized. is there anything that the static block accomplishes which a constructor can't?

推荐答案

如果一个类具有需要复杂初始化的静态成员, static 块是要使用的工具。假设您需要某种静态地图(目的与此无关)。你可以像这样在线声明它:

If a class has static members that require complex initialization, a static block is the tool to use. Suppose you need a static map of some kind (the purpose is irrelevant here). You can declare it in-line like this:

public static final Map<String, String> initials = new HashMap<String, String>();

但是,如果要填充一次,则不能使用内嵌功能宣言。为此,你需要一个 static 块:

However, if you want to populate it once, you can't do that with an in-line declaration. For that, you need a static block:

public static final Map<String, String> initials = new HashMap<String, String>();
static {
    initials.put("AEN", "Alfred E. Newman");
    // etc.
}

如果你想更加保护,你可以这样做:

If you wanted to be even more protective, you can do this:

public static final Map<String, String> initials;
static {
    HashMap<String, String> map = new HashMap<String, String>()
    map.put("AEN", "Alfred E. Newman");
    // etc.
    initials = Collections.unmodifiableMap(map);
}

请注意,您无法初始化首字母在线作为不可修改的地图因为那时你无法填充它!您也无法在构造函数中执行此操作,因为只需调用其中一个修改方法( put 等)将生成异常。

Note that you cannot initialize initials in-line as an unmodifiable map because then you couldn't populate it! You also cannot do this in a constructor because simply calling one of the modifying methods (put, etc.) will generate an exception.

公平地说,这不是你问题的完整答案。使用私有静态函数仍然可以消除 static 块:

To be fair, this is not a complete answer to your question. The static block could still be eliminated by using a private static function:

public static final Map<String, String> initials = makeInitials();

private static Map<String, String> makeInitials() {
    HashMap<String, String> map = new HashMap<String, String>()
    map.put("AEN", "Alfred E. Newman");
    // etc.
    return Collections.unmodifiableMap(map);
}

但请注意,这不会取代 static 阻止你提出的构造函数中的代码!

Note, though, that this is not replacing a static block with code in a constructor as you proposed!

static 替换将是一个笨拙的替换将是一个主类需要初始化几个其他类一次。

A case where a static block would be awkward to replace would be a "master" class that needs to initialize several other classes exactly once.

public class Master {
    static {
        SlaveClass1.init();
        SlaveClass2.init(SlaveClass1.someInitializedValue);
        // etc.
    }
}

特别是如果你不想在 SlaveClass1 上硬连接任何依赖到 SlaveClass2 ,需要这样的某种主代码。这种东西绝对不属于构造函数。

Particularly if you don't want to hard-wire any dependence into SlaveClass2 on SlaveClass1, some sort of master code like this is needed. This kind of stuff most definitely does not belong in a constructor.

请注意,还有一些叫做实例初始化程序块的东西。它是在创建每个实例时运行的匿名代码块。 (语法就像 static 块,但没有 static 关键字。)它对于匿名类特别有用,因为他们不能有命名的构造函数。这是一个真实的例子。由于(不可思议) GZIPOutputStream 没有构造函数或任何api调用,您可以使用它来指定压缩级别,并且默认压缩级别为none,您需要子类 GZIPOutputStream 获取任何压缩。你总是可以写一个显式的子类,但编写一个匿名类会更方便:

Note that there is also something called an instance initializer block. It is an anonymous block of code that is run when each instance is created. (The syntax is just like a static block, but without the static keyword.) It is particularly useful for anonymous classes, because they cannot have named constructors. Here's a real-world example. Since (unfathomably) GZIPOutputStream does not have a constructor or any api call with which you can specify a compression level, and the default compression level is none, you need to subclass GZIPOutputStream to get any compression. You can always write an explicit subclass, but it can be more convenient to write an anonymous class:

OutputStream os = . . .;
OutputStream gzos = new GZIPOutputStream(os) {
    {
        // def is an inherited, protected field that does the actual compression
        def = new Deflator(9, true); // maximum compression, no ZLIB header
    }
};

这篇关于Java中静态块的必要性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆