【问题标题】:difference between class level instantiation vs method instantiation类级实例化与方法实例化之间的区别
【发布时间】:2013-03-05 13:14:07
【问题描述】:

以下变量用法有什么区别

public class A{

    B b= new B();

    public void doSomething()
    {
        b.callme();
    }
}

VS

public class A { 
    B b;
    public void doSomething() {
        b=new B(); 
        b.callme();
    }
}

如果我们在一个类中只有一个“b”,那么哪个是更好的实践以及为什么。 以及在什么情况下使用。

【问题讨论】:

  • @SuKu:嗯,是的,你可以。它是一个实例变量初始化器。完全没问题。
  • 您的意思是第二种形式是b = new B();?您没有名为 B... 的变量
  • @JonSkeet 是的。 b=新的 B(); ...为错字道歉

标签: java class variables


【解决方案1】:

这些实际上有非常不同的含义。在情况 1 中,b 对象是在构造 A 时分配的。它只被构造一次(除非你从类外的某个地方重新分配它)。

在情况 2 中,每次调用该方法时,您都在重新分配 bA's 实例

【讨论】:

  • 当我们说对象被初始化一次时,那是关于类加载器(我正确吗)?
  • 我应该说“已分配”(帖子现在已编辑)。通过分配,我的意思是它现在引用 new B()
【解决方案2】:

这里真正的区别在于,每次调用 doSomething 时,您是否想要一个不同的 B 实例?在第二种情况下,这是正确的,但这也意味着如果有任何其他方法使用B,则您的类不是线程安全的。如果使用B 的类中没有任何其他方法,为什么不将其设为方法范围的变量?

【讨论】:

    【解决方案3】:

    Case 2:lazy initialization有帮助

    In case 1B 的对象是在创建A 的对象时创建的。但是如果创建B繁重的操作,那么你可以在真正需要B实例时懒惰地创建它。

    Lazy Initialization 在创建对象是一项繁重的任务并且您希望仅在实际使用对象实例时才延迟创建对象实例时很有帮助。但是如果你的类在线程之间共享,请注意thread safety

    更新:但在您的情况下,每次调用该方法时,您都会重新分配引用 b。这本身不是延迟初始化。

    //example of lazy initialization
    public B getB()
    {
      if (something =  = null)
        b = new B();
      return b;
    }
    

    【讨论】:

      【解决方案4】:

      Class level instantiation 将在创建类的新对象时实例化您的类变量。而method instantiation 将在调用该方法时实例化您的变量。

      良好实践:当您的类变量是/必须是 final 时,您应该使用 Class level instantiationinstantiate in Constructor,否则使用 method instantiationlazy initialization

      【讨论】:

        【解决方案5】:

        第一种情况称为内联初始化。它会在任何构造函数的主体运行之前但在调用超级构造函数之后发生。

        在第二种情况下,直到 doSomething 被调用(),b 才被初始化。

        至于哪个更好,这取决于你的程序逻辑。如果每次调用 doSomething 时都想要一个新实例,则第二种方法更好。如果您更喜欢延迟加载 b 则将其修改为

        if (b == null) b = new B(); 
        return b;
        

        我个人一般为了可读性而在构造函数中分配实例变量。

        public class A {
          B b;
        
          public A() {
            b = new B();
          } 
        }
        

        【讨论】:

          【解决方案6】:

          我只是在尝试类似的场景,但由于一个错误,我创建了一个递归场景(StackOverflow 错误):-

          public class Test{
          
          Test t=new Test();
          public static void main(String[] args) {
                 Test t=new Test();
                 System.out.println("Hello");
          }
          } 
          

          我认为这可能对某些概念性目的有所帮助。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-02-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-08-06
            相关资源
            最近更新 更多