【问题标题】:Default constructor is good or evil? Checkstyle and PMD are opposite here [closed]默认构造函数是好是坏? Checkstyle 和 PMD 在这里相反[关闭]
【发布时间】:2011-04-30 18:02:43
【问题描述】:

Checkstyle 说:

Class should define a constructor.

PMD 说:

Avoid unnecessary constructors - the compiler will generate these for you.

谁是对的?或者让我们这样说 - 在类中使用空的默认 ctor 有什么优缺点?

【问题讨论】:

  • 这只是风格问题。生成的代码是一样的。
  • 有趣的是,这两种观点已经在工具之间切换了位置...... PMD 现在敦促您使用默认构造函数,而 Checkstyle 不再关心了。

标签: java checkstyle pmd default-constructor


【解决方案1】:

我倾向于只在需要时才编写代码。如果您不需要任何其他构造函数,请让编译器为您生成它。否则,编写您需要的所有构造函数。

【讨论】:

    【解决方案2】:

    我喜欢 PMD 的回答。代码越少越好。不要编写编译器将为您编写的构造函数。

    我的印象是,编写构造函数的主要论据是,一些不了解构造函数在 Java 中如何工作的可怜程序员可能会绊倒您的代码并感到困惑。我不喜欢编写不必要的晦涩代码,但我也不喜欢编写愚蠢的代码。

    但这是我的强迫症,可能是不合理的。有一个应用程序程序员的世界,他们的中心焦点是业务,而不是语言,而且他们不是语言专家。很多人使用的生存技巧是保持一致的风格,是否绝对必要不是重点。

    【讨论】:

      【解决方案3】:

      IMO Class should define a constructor 因为如果您依赖默认构造函数,实例变量将具有默认值(例如整数为零,字符串为 null 等)。如果您想在创建该类的对象时将实例变量设置为某个默认值,那么在这种情况下,您自己定义构造函数可能是一个不错的选择。 (前提是你不想使用 getter 和 setter 方法)

      class Cube {
         private int length;
         private int breadth;
         private int height;
      
        public Cube() {
            length = 10;
            breadth = 10;
            height = 10;
        }
           ......
           ......
      }
      

      现在,当您创建 Cube1 类的对象时,该对象的所有实例变量都将设置为 10。如果您在这里不使用构造函数,您的实例变量(长度、宽度和高度)将具有默认值(在这种情况下为零)。


      已编辑:[添加了另一件事]

      如果您依赖编译器为您生成默认构造函数,并且您想使用一些从用户那里获取参数的构造函数,那么您必须定义默认构造函数,否则编译器会生成错误。

      记住:只有当你的类不包含任何其他构造函数时,编译器才会为你的类创建默认构造函数。

      【讨论】:

      • 嗯,你也可以初始化你声明它们的字段,比如private int length = 10;,因为它将字段和它的默认值联系在一起,可以说让事情变得更清楚。
      【解决方案4】:

      我要补充的一点是,如果没有指定构造函数,那么代码可能会依赖一个隐式默认构造函数。

      然后,当您添加特定的构造函数时,代码可能不再编译 - 或者更糟糕的是,代码将无法运行(可能是对无参数构造函数的反射依赖 - 大多数 ORM 工具都需要为持久实体提供默认构造函数)。

      这就是为什么您应该在需要时显式添加默认构造函数。

      【讨论】:

        【解决方案5】:

        与许多“有争议”的决定一样,事实是它真的没有那么重要。写或不写构造函数。对代码质量和可维护性的影响可以忽略不计。如果您与其他人一起编码,则采用相同的风格以保持一致性,否则 - 随心所欲。

        【讨论】:

        • +1 - 我想起了关于有多少天使可以在针头上跳舞的神学辩论......
        【解决方案6】:

        默认情况下编译器会为你生成默认构造函数,所以如果你不想指定任何特殊动作(这里不是初始化成员的重点),那么你不必指定构造函数。

        另一件事是某些类应该具有一致的状态。例如,您有一个 Book 类。创建没有标题的书是没有意义的,所以需要指定一个带字符串参数的构造函数:

        public Book(String name) {
            this.name = name;
        }
        

        至于默认构造函数,如果您应该序列化您的类或在编组/解组中使用它(JAXB 需要一个空的默认构造函数),它们可能是必需的。

        如果这不是重点,并且您的类没有所谓的一致状态,那么绝对不需要声明空的默认构造函数。

        您应该记住默认构造函数默认是公共的,因此如果您想对此进行一些限制,请考虑使用显式构造函数。

        另外,如果你的类比较长,你可以考虑声明一个空的默认构造函数来增加可读性。

        【讨论】:

          【解决方案7】:

          当默认构造函数是唯一的构造函数时,100% 等效于用空体显式编写或省略它。但是,如果您有任何显式定义的构造函数,无论是否默认,编译器都不会生成默认构造函数。这意味着如果您依赖编译器为您生成构造函数,然后添加替代构造函数,那么默认构造函数就会消失。就我个人而言,无论如何我倾向于让编译器进行生成;如果该默认构造函数正在使用中,它将生成编译警告并且很容易在此时添加。否则,为什么还要保留它呢?

          【讨论】:

            【解决方案8】:

            我会选择 Checkstyle。如果没有显式 (noarg) 构造函数,没有人会知道它是否有意。

            考虑这个实用程序类:

            public class Util {
                // no constructor given - implicit default constructor
                // intended? probably not, but who knows
            
                public static void foo() {
                  // blabla
                }
            
                public static void bar() {
                  // more blabla
                }
            
            }
            

            【讨论】:

            • 怎么可能不是故意的?如果使用它,并且没有其他构造函数,那么显然它一定是故意的。
            • 您必须在其他地方查看它是否已被使用,并且在任何情况下它都可能在将来被重构掉。我会说明确声明默认构造函数,然后如果这是一个只有静态方法的库类,请将构造函数标记为私有。
            • @andrewmu 是的,那是我的意图。
            【解决方案9】:

            虽然我有点像较少的代码,但使用默认构造函数可以更容易地在需要调试时设置断点。

            无论如何,我可以提醒你一下,PMD的网站也说这个问题是有争议的:)

            【讨论】:

              猜你喜欢
              • 2014-05-08
              • 1970-01-01
              • 2011-02-20
              • 1970-01-01
              • 2018-12-09
              • 2016-12-04
              • 1970-01-01
              • 2012-06-30
              • 1970-01-01
              相关资源
              最近更新 更多