【问题标题】:Java: Using Static Methods for repeated code sectionsJava:对重复的代码段使用静态方法
【发布时间】:2015-05-17 04:32:51
【问题描述】:

所以我正在学习 Java(gasp 打赌你永远猜不到),而今天我的重点是确保我正确使用静态方法。

我现在的大型实践计划是客户经理计划,随着我了解越来越多的概念,我会对其进行调整和添加。其中一个组件是打印出添加到系统中的所有帐户的列表。因为这个列表不止一次被调用,所以我创建了一个静态方法,可以调用它来生成它,并将它放在代码中我的 main 方法之上。

我的问题是:我应该这样做吗?为重复的代码部分创建这样的方法是一个好主意/好的编程礼仪吗?如果这两个问题的答案都是肯定的,我应该将其设为静态方法吗?

这是我所说的静态方法的代码:

/**
 * accountList() method displays a list of all accounts currently loaded into the program
 */
public static void accountList(){
    System.out.println("     ACCOUNT LIST");
    System.out.println("NUMBER      INFORMATION");
    for(int num = 0; num < accountArray.size(); num++){
        System.out.println("  " + (num + 1) + "         " + accountArray.get(num).getAccountName()
                         + " : " + moneyFormat.format(accountArray.get(num).getValue()) + " "
                         + accountArray.get(num).getCurrencyType());
    }
    listMax = accountArray.size();
}

然后这将是我的 main() 方法,并且在我的 main 中会定期调用此方法以生成帐户列表:

public static void main(String[] args){
    accountList(); //example of how I would invoke this method
}

那么,我是否正确地解决了这个问题?我正确使用它吗?谢谢。

附言。我的 accountList() 方法与我的 main() 方法在同一个类中,这就是为什么它之前没有类名的原因。这也是我要问的原因,因为我知道“静态”一词的主要目的之一是它可以很容易地从另一个类中访问,所以我不确定它是否需要是静态的,如果它在同一个类中类。

【问题讨论】:

  • 是的,创建小的、集中的方法是好的,因为它是一点点逻辑,你可以自己理解。它们是否应该是静态的取决于您使用它们的目的。但是,这种情况看起来不合适,因为您正在改变状态 (listMax),而可变静态状态通常不是一个好主意,因为它基本上是一个全局变量。

标签: java oop methods static


【解决方案1】:

类的静态成员(即变量、方法)与类的实例/对象无关/关联。无需创建类的对象即可访问它们。

使用静态方法的一般规则是——“问问自己一个类的属性或方法是否应该适用于该类的所有实例”。如果答案是肯定的,那么您可以使用静态成员。

考虑以下示例 -

public class Student{
    private int noOfStudent;
    .......

} 

现在你有一个Student 类型。在这种情况下,您可以考虑将noOfStudent 属性设为static。因为这不是 Student 本身的属性。因为一个班级的所有学生都应该共享noOfStudent 的相同属性。

你可以找到更多解释here

希望对您有所帮助。
非常感谢。

【讨论】:

    【解决方案2】:

    这就是静态方法。来自同一类的静态方法,您可以不使用类名调用,但是来自另一个类的静态方法,您必须使用类名调用。例如,如果您在名为 Class1 的类中有一个名为 method1 的静态方法,并且您试图在另一个名为 Class2 的类中调用该方法,则必须像这样调用该方法:

    Class1.method1();
    

    如果你只使用method1(),它会显示一个错误,它会告诉你它找不到方法,因为它只搜索你所在的类来寻找方法,并且它没找到。您必须输入类名 Class1,因此它知道要搜索 Class1 中的方法,而不是您所在的类。

    至于是否应该使用静态方法,这实际上取决于您的偏好。您知道静态方法和非静态方法之间的区别吗?我现在只给你一些基础知识。如果您有更多问题,您可以提问。

    好的。只有在方法所在的类中创建对象时才能调用非静态方法。这就是创建对象的方式:

    (CLASS NAME)(OBJECT NAME) = new (CONSTRUCTOR NAME)();
    

    构造函数的名称与类名相同。当你调用该方法时,你会输入 (OBJECT NAME).METHOD NAME();调用它。至于静态方法,我已经告诉过你如何调用它。所以。还有问题吗?

    【讨论】:

      【解决方案3】:

      静态方法的使用让人想起过程式编程。事实上,如果你使用静态方法,你就不能使用 OOP 原则,比如多态性。

      首先,以打印列表为目的的方法可能改变程序状态是不好的。然后,将来,您可能希望更改列表的打印方式。假设您想将其打印在文件中。如果您的 ar 使用静态方法,您将如何更改您的程序以满足这一新要求?

      尝试更多地考虑面向对象,并在开始时尝试将您的代码放在专用类中(即Printer)。然后,您可以从该类中提取一个接口,最后尝试应用一些设计模式,例如策略模式模板方法模式

      【讨论】:

        【解决方案4】:
        1. 为重复的代码部分创建这样的方法是一个好主意/良好的编程礼仪吗?

          用许多小方法代替较少的大方法在可维护性和可重用性方面是一种很好的做法。


        1. 我应该让它成为一个静态方法吗?

          当它们不依赖于类的某些特定实例的状态时,使用静态方法。通常会避免这种情况,因为子类型多态性不适用于静态方法(它们不能被覆盖)。小型实用程序方法被设为静态(如 Math.sqrtSystem.currentTimeMillis())。


        注意: (可选)

        当您定义方法以重用代码时,最重要的方面是该方法应该履行的契约。因此,这些方法应该使用参数相互通信并返回值以实现可预测的行为。改变类字段(甚至更糟糕的静态字段)的状态通常被认为是一个坏主意(尽管有时你必须这样做)。

        您可以改进您的方法,如下所示。

        public static void printAllAccounts(List<Account> accountList) {
            // Your code ...
        }
        

        此方法指定要打印的帐户,并且不依赖于状态。

        如果您可以将其委托给另一个类并使其成为非静态行为,那就更好了。这样,如果您想出更好的打印所有帐户的方法,您可以在不触及此方法的情况下替换该行为。

        希望这会有所帮助。
        祝你好运。

        【讨论】:

          【解决方案5】:

          Don't repeat yourself (DRY) 是一个被广泛接受的原则和良好实践,并且为否则会被复制的代码创建方法是最简单和最明显的形式。

          (在某些语言/上下文中,人们暗示方法调用的潜在开销及其对性能的影响。事实上,内联方法是编译器所做的常见优化。但现代编译器(尤其是 Java 虚拟机的即时编译器)会在适当的时候自动执行此操作)


          Whether helper methods should be static 已经在别处讨论过了。

          我的经验法则是:只要方法可以是静态的,那么它应该是静态的。

          更不同的观点:当方法不修改实例字段时(即,当它不操作可变状态),而是只对其参数进行操作并返回结果(在这个意义上是一个“函数”),并且它不应该涉及任何形式的多态性(意味着它不应该被重载),那么它通常应该被设为static(这里可能需要考虑单元测试的各个方面,但现在可能会走得太远)


          关于你的具体例子:

          这里有一个不同的问题:accountArray 显然是一个静态字段,listMax 变量也是如此。静态(非最终,可变)字段通常是一个可怕的想法。您应该肯定查看此内容,并尝试确保您没有描述状态static字段。

          如果你这样做了,你的方法仍然可以是静态的,并接收accountArray作为参数:

          public static void accountList(List<Account> accountArray){
              System.out.println("     ACCOUNT LIST");
              ...
          }
          

          但是,在这种形式下,它会违反另一个最佳实践,即Separation of Concerns。该方法做了两件事:

          • 它创建帐户的字符串表示形式
          • 它将这个字符串打印到控制台

          然后您可以将其拆分为两个或三个其他方法。根据缩进的用法,例如,这些可以是

          public static String createAccountInfoString(List<Account> accounts) {...}
          
          public static void printAccountInfo(List<Account> accounts, PrintStream ps) {
              ps.println(createAccountInfoString(accounts));
          }
          
          public static void printAccountInfo(List<Account> accounts) {
              printAccountInfo(accounts, System.out);
          }
          

          (请注意,方法名称表示方法做什么。像accountList 这样的方法名称不会告诉您任何事情!)。


          但是,正如其他人指出的那样:过度使用静态方法和传递信息可能表明没有正确使用面向对象的概念。您没有准确描述您将在那里建模的内容。但是根据关键字,您可能需要考虑将帐户列表封装在一个类中,例如 class AccountList,其中提供了一种将帐户列表打印到 PrintStream 的方法,例如 System.out

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-10-30
            • 2014-11-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-02
            • 2011-06-02
            • 1970-01-01
            相关资源
            最近更新 更多