抱歉标题错误,但我在mkyoung.com找到了下面列出的代码,并想知道这段代码的作用。这是Java中的一种方法,可以将某个默认值设置为变量吗?
public class LanguageBean implements Serializable{
private static Map<String,Object> countries;
static{
countries = new LinkedHashMap<String,Object>();
countries.put("English", Locale.ENGLISH); //label, value
countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}
}
答案 0 :(得分:25)
这个位声明一个静态字段:
private static Map<String,Object> countries;
所以它可以在课堂上直接访问,例如LanguageBean.countries
(或仅countries
),但仅限于类中的代码,因为它是私有的。
这个位是一个静态初始化器:
static{
countries = new LinkedHashMap<String,Object>();
countries.put("English", Locale.ENGLISH); //label, value
countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}
在加载类时,在创建任何实例之前运行,并且确实向countries
添加了一些条目。如果有多个静态初始值设定项,则它们以源代码顺序运行。请参阅this tutorial中的静态初始化程序块。
FWIW,还有这两个版本的每个实例版本。实例字段:
private int foo;
...和一个实例初始化器;他们看起来有点奇怪,因为他们只是在街区前面没有任何东西的块:
{
this.foo = 42;
}
在上下文中,以及第二个实例成员:
class Thing {
private int bar = 16; // An initializer on the declaration
private int foo;
// An instance initializer block
{
this.foo = 42; // Or just foo = 42;, but I prefer to be clear
}
}
所以你可以为实例做同样的事情。
答案 1 :(得分:6)
基本上是的,它正式称为静态初始化程序。并按JLS-8.7 Static Initializers
在类初始化(§12.4.2)时执行类中声明的静态初始化程序。与类变量(§8.3.2)的任何字段初始值设定项一起,静态初始值设定项可用于初始化类的类变量。
答案 2 :(得分:4)
这些被称为Static Initialization Blocks。
静态初始化块是用大括号{}括起来的常规代码块,前面是static关键字。这是一个例子:
static { // whatever code is needed for initialization goes here }
一个类可以有任意数量的静态初始化块,以及它们 可以出现在类体中的任何位置。运行时系统保证 静态初始化块按它们的顺序调用 出现在源代码中。
有静态块的替代方法 - 您可以编写私有块 静态方法:
class Whatever { public static varType myVar = initializeClassVariable(); private static varType initializeClassVariable() { // initialization code goes here } }
私有静态方法的优点是可以重用它们 稍后如果你需要重新初始化类变量。
每当初始化类时都会调用它们,并且可以用它们方便地初始化字段。
答案 3 :(得分:4)
使用静态初始化程序填充声明为countries
的静态变量Map
。有两个条目被添加到Map
。
static{
countries = new LinkedHashMap<String,Object>();
countries.put("English", Locale.ENGLISH); //label, value
countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}
的一个影响
静态初始化程序
是它在加载类时运行,并且该块是线程安全的,因此它用于设计模式,如singletons
等,以减少线程同步的需要。
有关详细信息,请参阅此主题: Are Java static initializers thread safe?
答案 4 :(得分:3)
以与想象对象的成员字段相同的方式来思考它。你可能有这样的事情:
private final Map<String, Object> countries;
public ClassName(){
countries = new LinkedHashMap<String,Object>();
countries.put("English", Locale.ENGLISH); //label, value
countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}
每次将new ClassName()
声明为某个“初始”状态时,这将初始化成员字段。以下内容:
static{
countries = new LinkedHashMap<String,Object>();
countries.put("English", Locale.ENGLISH); //label, value
countries.put("Chinese", Locale.SIMPLIFIED_CHINESE);
}
...基本上做同样的事情,除了静态字段。现在,当加载类时,将调用此静态块并初始化静态字段,然后才能使用它们以使它们具有某种“初始”状态。当你有一些不会改变的东西时(例如你可能想要设置一个能够轻松查找某些东西的地图),或者当你需要设置一些可能会引发异常而你正在尝试的事情时,通常会使用这种方法。设置确实应该是静态的,例如:
private static KeyPairGenerator KPG;
static {
try {
KPG = KeyPairGenerator.getInstance("RSA");
KPG.initialize(2048);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.err.println("Couldn't get a Key Pair Generator...exiting");
System.exit(1);
}
}
在上面的例子中,我只需要一个KeyPairGenerator
用于所有我的类(假设我总是使用密钥大小为2048的RSA加密)。使用此单KeyPairGenerator
,我可以生成多个公钥。但是,创建KeyPairGenerator
会抛出NoSuchAlgorithm
异常(由于Java需要支持密钥长度为2048的RSA,因此不会发生此异常)。所以我仍然可以通过使用这个静态初始化器来获取静态KeyPairGenerator
。
答案 5 :(得分:0)
它用于创建变量并在类加载期间初始化它(即当执行static {}块时)。
作为Java语言规范状态:
静态初始化器(第8.7节)是可执行代码块 用于帮助初始化一个类。
它确实常用于小型教程中初始化值。
另一方面,他们也可以使用“更大”的程序。您也可以在Factory对象中使用它注册类。在这种情况下,每个具体产品在工厂中注册。通过这样做,您不必在添加新的具体产品时修改工厂类。
class OneProduct extends Product
{
...
static
{
ProductFactory.instance().registerProduct("ID1", new OneProduct());
}
public OneProduct createProduct()
{
return new OneProduct();
}
...
}