加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

从java构造函数调用实例方法是好还是坏的做法?

发布时间:2020-12-14 05:35:08 所属栏目:Java 来源:网络整理
导读:有几种不同的方法可以初始化复杂的对象(注入的依赖关系和注入成员的所需设置),这些都看起来很合理,但有各种各样的优点和缺点.我会举一个具体的例子: final class MyClass { private final Dependency dependency; @Inject public MyClass(Dependency depend
有几种不同的方法可以初始化复杂的对象(注入的依赖关系和注入成员的所需设置),这些都看起来很合理,但有各种各样的优点和缺点.我会举一个具体的例子:
final class MyClass {
  private final Dependency dependency;
  @Inject public MyClass(Dependency dependency) {
    this.dependency = dependency;
    dependency.addHandler(new Handler() {
      @Override void handle(int foo) { MyClass.this.doSomething(foo); }
    });
    doSomething(0);
  }
  private void doSomething(int foo) { dependency.doSomethingElse(foo+1); }
}

你可以看到,构造函数做了3件事情,包括调用一个实例方法.我被告知,从构造函数调用实例方法是不安全的,因为它规避了未初始化成员的编译器检查.即我可以在设置this.dependency之前调用doSomething(0),这将被编译但没有工作.什么是最好的方式来重构这个?

>使doSomething静态并显式传递依赖关系在我实际的情况下,我有三个实例方法和三个成员字段,它们都相互依赖,所以这似乎是很多额外的样板,使所有这三个静态.
>将addHandler和doSomething移动到@Inject public void init()方法中.与Guice一起使用将是透明的,它需要任何手动构造来确保调用init(),否则如果有人忘记,对象将不会完全正常.此外,这暴露了更多的API,这两个似乎都是坏主意.
>包装一个嵌套类以保持依赖关系,以确保其正常运行,而不会暴露其他API:

class DependencyManager {
  private final Dependency dependency;
  public DependecyManager(Dependency dependency) { ... }
  public doSomething(int foo) { ... }
}
@Inject public MyClass(Dependency dependency) {
  DependencyManager manager = new DependencyManager(dependency);
  manager.doSomething(0);
}

这将实例方法从所有构造函数中抽出,但是会生成一个额外的类,当我已经拥有内部和匿名类(例如处理程序)时,可能会变得混乱 – 当我尝试这一点时,被告知要将DependencyManager移动到单独的文件,这也是令人讨厌的,因为它现在是多个文件做一件事情.

那么处理这种情况的首选方式是什么?

解决方法

有效Java中的Josh Bloch建议使用静态工厂方法,尽管我找不到任何参数.然而,在 Java Concurrency in Practice年有一个类似的情况,专门用于防止从构造函数中泄漏引用.适用于这种情况,它看起来像:
final class MyClass {
  private final Dependency dependency;

  private MyClass(Dependency dependency) {
    this.dependency = dependency;
  }

  public static createInstance(Dependency dependency) {
    MyClass instance = new MyClass(dependency);
    dependency.addHandler(new Handler() {
      @Override void handle(int foo) { instance.doSomething(foo); }
    });
    instance.doSomething(0);
    return instance;
  }
  ...
}

但是,使用DI注释可能无法正常工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读