为了账号安全,请及时绑定邮箱和手机立即绑定

在Java中使用初始化程序与构造函数

在Java中使用初始化程序与构造函数

12345678_0001 2019-10-05 15:23:32
因此,最近我一直在提高自己的Java技能,并且发现了一些以前不了解的功能。静态和实例初始化程序是两种这样的技术。我的问题是,何时将使用初始化程序而不将代码包含在构造函数中?我想到了几个明显的可能性:静态/实例初始化器可用于设置“最终”静态/实例变量的值,而构造函数无法静态初始值设定项可用于设置类中任何静态变量的值,该值应比在每个构造函数的开头使用“ if(someStaticVar == null)//做东西”代码块更有效。这两种情况都假设设置这些变量所需的代码比简单地“ var = value”要复杂得多,否则,似乎没有任何理由使用初始化程序而不是在声明变量时简单地设置值。然而,尽管这些并不是微不足道的收益(尤其是设置最终变量的能力),但似乎确实有少数情况下应该使用初始化器。当然,在构造函数中可以完成很多事情,但是可以使用初始化程序,但是我真的不知道这样做的原因。即使一个类的所有构造函数都共享大量代码,使用私有的initialize()函数对我来说似乎比使用初始化程序更有意义,因为在编写新代码时,它不会使您锁定代码运行构造函数。我想念什么吗?在其他情况下,应该使用初始化程序吗?还是在非常特殊的情况下使用它真的只是一个相当有限的工具?
查看完整描述

3 回答

?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

静态初始化程序对于cletus很有用,我以相同的方式使用它们。如果您有一个静态变量要在加载类时进行初始化,则可以使用静态初始化程序,尤其是因为它允许您执行复杂的初始化操作并且仍然具有静态变量be final。这是一个巨大的胜利。


我发现“ if(someStaticVar == null)//做东西”是混乱且容易出错的。如果它是静态初始化并声明的final,则避免了它的可能性null。


但是,当您说:


静态/实例初始化器可用于设置“最终”静态/实例变量的值,而构造函数无法


我假设您同时在说:


静态初始值设定项可用于设置“最终”静态变量的值,而构造函数不能

实例初始化器可用于设置“最终”实例变量的值,而构造函数不能

而您在第一点上是正确的,在第二点上是错误的。例如,您可以执行以下操作:


class MyClass {

    private final int counter;

    public MyClass(final int counter) {

        this.counter = counter;

    }

}

同样,当构造函数之间共享大量代码时,处理此问题的最佳方法之一是链接构造函数,并提供默认值。这很清楚地表明正在做什么:


class MyClass {

    private final int counter;

    public MyClass() {

        this(0);

    }

    public MyClass(final int counter) {

        this.counter = counter;

    }

}


查看完整回答
反对 回复 2019-10-05
?
千万里不及你

TA贡献1784条经验 获得超9个赞

我最经常使用静态初始化程序块来设置最终的静态数据,尤其是集合。例如:


public class Deck {

  private final static List<String> SUITS;


  static {

    List<String> list = new ArrayList<String>();

    list.add("Clubs");

    list.add("Spades");

    list.add("Hearts");

    list.add("Diamonds");

    SUITS = Collections.unmodifiableList(list);

  }


  ...

}

现在,可以使用单行代码完成此示例:


private final static List<String> SUITS =

  Collections.unmodifiableList(

    Arrays.asList("Clubs", "Spades", "Hearts", "Diamonds")

  );

但是静态版本可以整洁得多,尤其是当这些项目对于初始化而言并非简单时。


天真的实现也可能不会创建不可修改的列表,这是潜在的错误。上面创建了一个不变的数据结构,您可以从公共方法等中愉快地返回。


查看完整回答
反对 回复 2019-10-05
?
慕神8447489

TA贡献1780条经验 获得超1个赞

只是为了补充一些已经很不错的观点。静态初始化程序是线程安全的。它在加载类时执行,从而使静态数据初始化比使用构造函数更简单,在构造函数中,您将需要一个同步块来检查静态数据是否已初始化,然后进行实际初始化。


public class MyClass {


    static private Properties propTable;


    static

    {

        try 

        {

            propTable.load(new FileInputStream("/data/user.prop"));

        } 

        catch (Exception e) 

        {

            propTable.put("user", System.getProperty("user"));

            propTable.put("password", System.getProperty("password"));

        }

    }


public class MyClass 

{

    public MyClass()

    {

        synchronized (MyClass.class) 

        {

            if (propTable == null)

            {

                try 

                {

                    propTable.load(new FileInputStream("/data/user.prop"));

                } 

                catch (Exception e) 

                {

                    propTable.put("user", System.getProperty("user"));

                    propTable.put("password", System.getProperty("password"));

                }

            }

        }

    }

别忘了,您现在必须在类而不是实例级别进行同步。这将为每个构造的实例产生一个成本,而不是在加载类时产生一次成本。另外,这很丑;-)


查看完整回答
反对 回复 2019-10-05
  • 3 回答
  • 0 关注
  • 460 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信