【问题标题】:Is it a good practice to call a method in my constructor? [duplicate]在构造函数中调用方法是一种好习惯吗? [复制]
【发布时间】:2020-01-11 01:53:07
【问题描述】:

我有以下类,我想在其中自动生成 premium 的值:

public class MedicalPolicy implements PolicyType {

    private int id;
    private LocalDate effective;
    private LocalDate expiry;
    private String policyNo;
    private double premium;
    private ArrayList<Beneficiary> beneficiaries;

    public MedicalPolicy(LocalDate effective,LocalDate expiry,ArrayList<Beneficiary> beneficiaries){
        this.id=0;
        this.effective=effective;
        this.expiry=expiry;
        this.beneficiaries=beneficiaries;
        this.premium=getPremiumByCalculation();
        this.policyNo= Integer.toString(LocalDate.now().getYear()) + "-Medical-" + Integer.toString(id);
    }

    private double getPremiumByCalculation(){
        //do some calculation based on some criteria
    }
}

像我一样使用方法来计算保费是一种好习惯还是有更好的方法?

【问题讨论】:

  • 是的。没关系。为什么不呢?
  • 也许你应该阅读这篇stackoverflow.com/questions/18348797/…
  • 做任何事情都会导致最干净的代码。除非您注意到有充分的理由担心,否则不要担心此类小事。
  • 只要该方法不可被覆盖,就可以了。
  • 在你的情况下,它是一个private 方法,因此不可覆盖,因此很好。但是,非final 类中的public、非final 方法将是另一回事......

标签: java constructor


【解决方案1】:

不,这是个糟糕的主意

不要在部分构造的对象上调用方法。你可能会认为你可以计算出它已经足够构造,或者如果你查看代码你看到它可能会工作,但是其他所有人都必须进行扣除,然后进行维护。

Swing 做了很多这样的事情,而且一团糟。导致各种NullPointerExceptions。

一定要分解出一个方法,但不要让它成为同一个实例的实例方法。这段代码的一个特殊问题是,看起来premium 需要随着每次更改而更新,这将是非常脆弱的。

【讨论】:

    【解决方案2】:

    这不好,因为字段(甚至是最终字段!)可能没有您期望的值。有点先有鸡还是先有蛋的场景:您的方法会假定对象已完全构造,但在方法完成之前不可能完全构造对象。

    通常的首选替代方法是静态方法。这避免了整个喧嚣。这确实意味着您必须传递运行此计算所需的实际信息位,但这实际上是一件好事:它使需要哪些信息更加清晰,并且更易于测试。

    我注意到您的字段不是最终的;我假设确定“溢价”的计算取决于这些非最终字段中的至少一个。在这种情况下,您是否考虑过更新该字段时会发生什么?通常,解决此问题的最简单方法是使所有字段成为最终字段,并使其成为不可变对象,巧妙地回避“但如果更新了怎么办?”问题。

    第二个简单的解决方案是完全删除高级字段并每次重新计算。如果都是数学(指数和对数等的一些乘法和应用),那么 CPU 的速度非常快。事实上,一个 CPU 可以在进行一次内存查找所需的时间内执行 300 到 500 条指令(我过于简单化了,因为相邻字段的内存查找通常来自同一个缓存页面,因此实际上是免费的,但是,嘿,如果它必须首先获取那个缓存页面,一旦我们已经进入了 500 个周期,为什么还要担心另外 4 个周期,对吧?也许让这个对象少占用两倍的内存实际上可以节省缓存查找稍后,因此更快——没有分析器报告,不要猜测,选择更容易编写的代码,完全摆脱 premium 听起来在这里会更简单。让每个人都调用 getPremiumByCalculation()时间(并将其重命名为 getPremium())。

    【讨论】:

      【解决方案3】:

      在我看来,这并没有什么问题。您可以测试它是否适用于简单的 JUnit 文件,但如果可以,则继续。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-01
        • 2021-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-15
        • 2016-12-11
        • 1970-01-01
        相关资源
        最近更新 更多