简体   繁体   English

对象初始化时调用方法

[英]call a method when an object is initializing

I'm extending from an abstract class named ChildClass , it has 4 constructors which should be implemented. 我从一个名为ChildClass的抽象类扩展,它具有4个应实现的构造函数。
There is a set of general configuration common to all constructors. 所有构造函数都有一组通用配置。
I could abstract these tasks and call it in all constructors. 我可以抽象这些任务,并在所有构造函数中调用它。
Is there anyway to call a specif method when an object is going to be initialized rather than calling it in all of the constructor signatures? 无论如何,当要初始化一个对象而不是在所有构造函数签名中调用它时,是否仍要调用specif方法?

Since Java compiler must ensure a call to a constructor of the base class, you can place the common code in a constructor of your abstract base class: 由于Java编译器必须确保对基类的构造函数的调用,因此可以将通用代码放在抽象基类的构造函数中:

abstract class BaseClass {
    protected BaseClass(/*put arguments here*/) {
        // Code that is common to all child classes
    }
}
class ChildClassOne extends BaseClass {
    public ChildClassOne(/*put arguments here*/) {
       super(arg1, arg2, ...);
       // More code here
    }
}

You can declare an instance method in the class which can be called from a constructor like this: 您可以在类中声明一个实例方法,该实例方法可以从这样的构造函数中调用:

Class A{
  public A(){
     initialize();
  }

  public void initialize(){
     //code goes here
  }
}

This concept extends to abstract classes as well. 这个概念也扩展到抽象类。

You could chain your constructors. 您可以链接您的构造函数。

public class Test {

    public Test() {
        // Common initialisations.
    }

    public Test(String stuff) {
        // Call the one ^
        this();
        // Something else.
    }

You can then put your common code in the () constructor. 然后,您可以将常用代码放入()构造函数中。

As already stated in the comment, one way to call common initialization code would be the use of this(...) , ie you'd call one constructor from another. 如注释中所述,调用通用初始化代码的一种方法是使用this(...) ,即您可以从另一个调用一个构造函数。 The problem, however, is that this call would have to be the first statement of a constructor and thus might not provide what you want. 但是,问题在于此调用必须是构造函数的第一条语句,因此可能无法提供所需的内容。

Alternatively you could call some initialization method (the most common name would be init() ) in all constructors and in a place that is appropriate (eg at the end of the constructor). 或者,您可以在所有构造函数中和适当的位置(例如,在构造函数的末尾)调用某种初始化方法(最常用的名称是init() )。 There is one problem though: if a subclass would override that method it could create undefined situations where the super constructor calls the method and the method uses non-yet-initialized fields of the subclass. 但是,存在一个问题:如果子类将覆盖该方法,则它可能会创建未定义的情况,其中超级构造函数将调用该方法,而该方法将使用子类的尚未初始化的字段。 To mitigate that the method should not be overridable, ie declare it final or make it private (I'd prefer to have it final though because that's more explicit). 为了减轻该方法不应被重写的影响,即,将其声明为final或将其设为私有(我更希望将其声明为final,因为它更为明确)。

Depending on your needs there's a 3rd option: use the initializer block: 根据您的需要,有第三个选项:使用初始化块:

class Super {
  {
    //this is the initializer block that is called before the corresponding constructors 
    //are called so it might or might not fit your needs
  }
}

Here's an example combining all 3 options: 这是结合所有3个选项的示例:

static class Super {
  {
    //called before any of the Super constructors
    System.out.println( "Super initializer" );
  }

  private final void init() {
    System.out.println( "Super init method" );
  }

  public Super() {
    System.out.println( "Super common constructor" );
  }

  public Super(String name) {
    this(); //needs to be the first statement if used
    System.out.println( "Super name constructor" );
    init(); //can be called anywhere
  }
}

static class Sub extends Super {
  {
    //called before any of the Sub constructors
    System.out.println( "Sub initializer" );
  }

  private final void init() {
    System.out.println( "Sub init method" );
  }

  public Sub() {
    System.out.println( "Sub common constructor" );
  }

  public Sub(String name) {
    super( name ); //needs to be the first statement if used, calls the corrsponding Super constructor
    System.out.println( "Sub name constructor" );
    init(); //can be called anywhere
  }
}

If you now call new Sub("some name") , you'll get the following output: 如果现在调用new Sub("some name") ,则会得到以下输出:

Super initializer
Super common constructor
Super name constructor
Super init method
Sub initializer
Sub name constructor
Sub init method

An alternative is to use an Initializer block . 一种替代方法是使用Initializer块

Class A {
  {
    // initialize your instance here...
  }
  // rest of the class...
}

The compiler will make sure the initializer code is called before any of the constructors. 编译器将确保在任何构造函数之前调用初始化程序代码。

However, I would hesitate a bit to use this use this - perhaps only if there are no other alternatives possible (like putting the code in a base class). 但是,我会犹豫使用此方法-也许只有在没有其他替代方法(例如将代码放在基类中)的情况下,才能使用此方法。

If you can put the common code in one constructor and call it as the first instruction from the other constructors, it is the Java idiomatic way. 如果可以将通用代码放在一个构造函数中,并作为其他构造函数的第一条指令调用它,则这是Java惯用的方式。

If your use case is more complex, you can call a specific method from the constructors provided it is private, final or static (non overidable). 如果您的用例更复杂,则可以从构造函数中调用特定的方法, 前提是该方法是私有的,最终的或静态的 (不可覆盖)。 An example use case would be: 一个示例用例将是:

class Test {
    private final void init(int i, String str) {
        // do common initialization
    }
    public Test(int i) {
        String str;
        // do complex operations to compute str
        init(i, str);    // this() would not be allowed here, because not 1st statement
    }

    public Test(int i, String str) {
        init(i, str);
    }

}

Make a common method and assign it to instance variable. 制作一个通用方法并将其分配给实例变量。 Another way of doing it. 另一种方式。

import java.util.List;

public class Test {
     int i = commonMethod(1);

    Test() {
        System.out.println("Inside default constructor");
    }

    Test(int i) {
        System.out.println("Inside argument  Constructor ");
    }

    public int commonMethod(int i) {
        System.out.println("Inside commonMethod");
        return i;
    }

    public static void main(String[] args) {
        Test test1 = new Test();
        Test test2 = new Test(2);

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM