Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在构造函数结束后调用方法_Java - Fatal编程技术网

Java 在构造函数结束后调用方法

Java 在构造函数结束后调用方法,java,Java,我需要在构造函数结束后调用一个方法,我不知道该怎么做。 我有这门课: Class A { public A() { //... } public void init() { //Call after the constructor } } 您必须在客户端执行此操作,因此: A a = new A(); a.init(); 或者您必须在构造函数末尾执行此操作: class A { public A() {

我需要在构造函数结束后调用一个方法,我不知道该怎么做。 我有这门课:

Class A {
    public A() {
        //...
    }

    public void init() {
        //Call after the constructor
    }
}

您必须在客户端执行此操作,因此:

A a = new A();
a.init();
或者您必须在构造函数末尾执行此操作:

class A {
    public A() {
        // ...
        init();
    }

    public final void init() {
        // ...
    }
}
但是,不建议使用第二种方法,除非将该方法设置为私有或最终方法


另一种选择是使用工厂方法:

class A {
    private A() {  // private to make sure one has to go through factory method
        // ...
    }
    public final void init() {
        // ...
    }
    public static A create() {
        A a = new A();
        a.init();
        return a;
    }
}

相关问题:

    • 为什么不这样做:

      Class A {
          public A() {
              //... Do you thing
              this.init();
          }
      
          public void init() {
              //Call after the constructor
          }
      }
      
      这个怎么样:

      Class A {
          public A() {
              // to do
              init();
          }
      
          public void init() {
              //Call after the constructor
          }
      }
      

      到目前为止你做了什么?你看起来像这样吗

        Class A {
              public A() {
                  //...
              }
      
              public void init() {
                  //Call after the constructor
              }
          }
      
           public static void main(String[] args)
          {
          A a = new A();
      
          a.init();
      }
      

      您需要一个静态工厂方法来构造对象,调用init方法,最后返回对象:

      class A {
          private A() {
              //...
          }
      
          private void init() {
              //Call after the constructor
          }
      
          public static A create() {
              A a = new A();
              a.init();
              return a;
          }
      }
      

      请注意,我已将构造函数和
      init()
      方法设置为私有,因此它们只能由工厂方法访问。客户端代码将通过调用
      A.create()
      而不是调用构造函数来创建对象。

      我收集了一些想法,并提供了一个可抽象的解决方案:

      class A {
          protected A() {
              // ...
          }
          protected void init() {
              // ...
          }
          public static <T extends A> T create(Class<T> type) {
              try {
                  T obj = type.newInstance();
                  obj.init();
                  return obj;
              } catch (ReflectiveOperationException ex) {
                  System.err.println("No default constructor available.");
                  assert false;
                  return null;
              }
          }
      }
      
      A类{
      保护A(){
      // ...
      }
      受保护的void init(){
      // ...
      }
      公共静态T创建(类类型){
      试一试{
      T obj=type.newInstance();
      obj.init();
      返回obj;
      }捕捉(反射操作例外){
      System.err.println(“没有可用的默认构造函数”);
      断言错误;
      返回null;
      }
      }
      }
      
      如果要在构造函数之前调用方法,可以使用初始值设定项块


      如果
      init()
      启动一个新线程或将其
      引用与另一个可能从另一个线程访问该引用的类共享,则不应在构造函数中调用它。如果你这样做,你将有一个数据竞赛。如果你直接在构造函数中这样做,同样的问题也会出现。如果将部分构造委托给
      init
      方法,则没有区别。问题是当
      init
      方法可能被子类重写时。如果使用静态工厂方法,您可能也希望将
      init
      方法设置为私有。如果问题是与其他线程共享
      引用,则会产生不同,因为一旦构造函数完成,类的不变量可能会得到保证,特别是任何最终字段都会保证在其他线程中可见。@aioobe事实上,它的内联也有这个bug,这不会影响我的评论,imho
      init()
      方法通常发布
      this
      或派生线程——这就是为什么它们是独立的方法,而不仅仅是在构造函数中。鉴于construct than init模式与init does thread内容有着相对较高的相关性,我认为明确指出这种危险是有帮助的。那么,我想我们在我的评论的相关性上不会有一致的看法。因此,我将把它作为一个注释留给OP:如果您的
      init()
      方法将
      this
      暴露给任何人(另一个线程、另一个类等),那么您将暴露于微妙的数据争用错误中。这样做的风险自负。有些答案似乎是假设init可以简单地在构造函数中移动,但我假设它所做的任何事情都不适合在构造函数中进行(例如注册侦听器,这样就有机会看到部分构造的对象),否则就没有必要问这个问题了。好主意,但如果这些东西是私人的,你就不需要工厂了。您只需在构造函数末尾调用它。但是,如果方法和构造函数受到保护,您可以使用工厂作为一个好的解决方案,以确保重写构造函数不会导致缺少init()调用。当然,如果构造函数是受保护的,并且类是可抽象的,那么您需要一个更通用的工厂方法-忘了提到它了。@UniversE不,您不能简单地在构造函数末尾调用它。Java特别保证构造函数完成后最终字段的可见性。如果将对该对象的引用传递给另一个线程,它可能会看到这些字段的默认值,这在构造函数完成后不会发生。但是如果在构造函数末尾调用它,该方法将在同一线程上执行,并且不会出现可见性问题。@aioobe如果在构造函数末尾调用它,而
      init()
      允许引用
      转义,另一个线程可以在构造函数完成之前检查对象。请参阅yshavit对这个问题的另一个答案的评论。让
      this
      在对象完全初始化之前逃逸是一个糟糕的想法,不管它是从构造函数还是从init方法完成的,也不管是否有多个线程。据我所知,这是处理继承的唯一答案。还是我错了?在这种情况下,构造函数是不完整的。构造函数在运行此.init()之后完成。一般来说,在自己的构造函数中使用它来运行方法是不好的做法,因为构造函数没有完全创建。通常,当你有多个线程时,这会把事情搞砸。@GeorgeXavier你是对的,谢谢你指出这一点。编辑了答案,所以现在这是显而易见的。
      class A {
          { 
              init() 
          }
      
          public A() {
              //todo
          }
      
          private final void init() {
             //todo
          }
      }