Java 实例初始值设定项与构造函数有何不同?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1355810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:05:00  来源:igfitidea点击:

How is an instance initializer different from a constructor?

javainstantiation

提问by Ajay

In other words, why would you need an instance initializer? What difference or advantage do you have in writing a instance initializer over a constructor?

换句话说,你为什么需要一个实例初始化器?在编写实例初始化程序而不是构造函数时,您有什么区别或优势?

采纳答案by javamonkey79

This seems to explain it well:

这似乎很好地解释了它:

Instance initializers are a useful alternative to instance variable initializers whenever:

  • initializer code must catch exceptions, or

  • perform fancy calculations that can't be expressed with an instance variable initializer. You could, of course, always write such code in constructors.

But in a class that had multiple constructors, you would have to repeat the code in each constructor. With an instance initializer, you can just write the code once, and it will be executed no matter what constructor is used to create the object. Instance initializers are also useful in anonymous inner classes, which can't declare any constructors at all.

在以下情况下,实例初始值设定项是实例变量初始值设定项的有用替代:

  • 初始化代码必须捕获异常,或

  • 执行不能用实例变量初始值设定项表达的奇特计算。当然,您可以始终在构造函数中编写此类代码。

但是在具有多个构造函数的类中,您必须在每个构造函数中重复代码。使用实例初始化程序,您只需编写一次代码,无论使用什么构造函数创建对象,它都会执行。实例初始化器在匿名内部类中也很有用,它根本不能声明任何构造函数。

From: JavaWorld Object initialization in Java.

来自:Java 中的JavaWorld Object 初始化

回答by Rahul Garg

When you have many constructors and want some common code to be executed for each constructor you can use instance initializer.As it is called for all constructors.

当您有许多构造函数并希望为每个构造函数执行一些公共代码时,您可以使用实例初始化程序。因为它被所有构造函数调用。

回答by ykaganovich

In terms of object lifecycle, there is no difference. Both are invoked at construction time, and logically the initializer block can be considered part of construction.

在对象生命周期方面,没有区别。两者都在构造时调用,逻辑上初始化块可以被视为构造的一部分。

Semantically, an initializer is a nice tool to have for several reasons:

从语义上讲,初始化程序是一个很好的工具,原因如下:

the initializer can improve code readability by keeping the initialization logic next to the variable being initialized:

初始化器可以通过将初始化逻辑保持在被初始化的变量旁边来提高代码可读性:

   public class Universe {
       public int theAnswer;
       {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;
       }

       // a bunch of other vars
   }

vs

对比

   public class Universe {
       public int theAnswer;

       // a bunch of other vars

       public Universe() {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;

         // other constructor logic
       }
   }

Initializers are invoked regardless of which constructor is used.

无论使用哪个构造函数,都会调用初始化程序。

Initializers can be used in anonymous inner classes, where constructors can't.

初始化器可用于匿名内部类,而构造器则不能。

回答by CPerkins

I would avoid the instance initializer idiom in general - the only real advantage it gives over variable initializers is exception handling.

一般来说,我会避免使用实例初始值设定项——它比变量初始值设定项的唯一真正优势是异常处理。

And since an init method (callable from constructor) can also do exception handling and also centralizes constructor setup code, but has the advantage that it can operate on constructor parameter values, I'd say that the instance initializer is redundant, and therefore to be avoided.

并且由于 init 方法(可从构造函数调用)也可以进行异常处理并集中构造函数设置代码,但具有可以对构造函数参数值进行操作的优点,我会说实例初始值设定项是多余的,因此避免了。

回答by dnyanesh

Initializer is way to share code between constructors and it make code more readable if initializer is used with variable declaration.

初始化程序是在构造函数之间共享代码的方式,如果初始化程序与变量声明一起使用,它会使代码更具可读性。

The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors. Oracle documentation

Java 编译器将初始化块复制到每个构造函数中。因此,这种方法可用于在多个构造函数之间共享代码块。 甲骨文文档

回答by padippist

The real advantage of instance initializers over constructors is seen when we use an anonymous inner class.

当我们使用匿名内部类时,可以看到实例初始化器相对于构造器真正优势

Anonymous inner classes can't have a constructor(as they're anonymous),sothey're a pretty natural fit for instance initializers.

匿名内部类不能有构造函数(因为它们是匿名的)因此它们非常适合实例初始化程序

回答by NPE

At the time of object creation, if we want to perform initialise of instance variables, then we should go for Constructor, other than initialisation activity if we want to perform any activity at the time of object creation then we should go for instance block.

在创建对象的时候,如果我们要执行实例变量的初始化,那么我们应该去构造函数,而不是初始化活动,如果我们要在创建对象时执行任何活动,那么我们应该去实例块。

We can't replace constructor with instance block because constructor can take argument but instance block can't take arguments.

我们不能用实例块替换构造函数,因为构造函数可以带参数但实例块不能带参数。

We can't replace instance block wih constructor because a class can contain more than one constructor. If we want to replace instance block with constructor then in every constructor we have to write instance block code because at runtime which constructor will be called we can't expect, this will unnecesarily increase duplicate code.

我们不能用构造函数替换实例块,因为一个类可以包含多个构造函数。如果我们想用构造函数替换实例块,那么在每个构造函数中我们必须编写实例块代码,因为在运行时我们无法预料会调用哪个构造函数,这将不必要地增加重复代码。

Example :

例子 :

class MyClass{

    static int object_count = 0;

    MyClass(){
        object_count++;
    }

    MyClass(int i){

        object_count++;
    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

Output :2

输出 :2

class MyClass{

    static int object_count = 0;

    {
        object_count++;
    }

    MyClass(){

    }

    MyClass(int i){     

    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

Output :2

输出 :2