对于只有静态字段和方法的类来说,这是不好的做法吗?

时间:2009-12-21 21:57:53

标签: oop class static

我有一个包含静态成员变量和静态方法的类。从本质上讲,它是一个通用的实用类。

类只包含静态成员变量和静态方法是不好的做法?

15 个答案:

答案 0 :(得分:88)

不,我根本不这么认为。更糟糕的做法是让一个完整的实例方法的类实际上不依赖于特定的实例。使它们静态告诉用户他们打算如何使用它们。此外,您可以通过这种方式避免不必要的实例化。

编辑:作为一个事后的想法,总的来说,我认为避免使用语言功能“只是因为”,或者因为你认为那是“Java方法”,这很好。我记得我的第一份工作,我有一个充满静态实用方法的课程,其中一位高级程序员告诉我,我并没有充分利用Java的OO能力,使我的所有方法都“全局化”。 6个月后她没有加入团队。

答案 1 :(得分:18)

只要该类没有内部状态,并且本质上是所谓的叶类(实用程序类属于此类),换句话说,它独立于其他类。没关系。

Math类是一个主要的例子。

答案 2 :(得分:13)

听起来很合理。

注意:执行此操作的类通常只有一个私有的无参数构造函数,这样如果程序员尝试创建静态类的实例,编译器就会产生错误。

答案 3 :(得分:9)

静态方法不用担心我(测试除外)。

一般来说,静态成员是一个问题。例如,如果您的应用是群集的,该怎么办?启动时间怎么样 - 正在进行什么样的初始化?如需考虑这些问题以及更多问题,请查看Gilad Bracha撰写的this article

答案 4 :(得分:3)

这是完全合理的。实际上,在C#中,您可以使用static关键字专门为此目的定义一个类。

答案 5 :(得分:3)

只是不要被它带走。请注意,java.lang.Math类仅与数学函数有关。您可能还有一个StringUtilities类,其中包含常见的字符串处理函数,例如,这些函数不在标准API中。但是,如果您的类名为Utilities,那么您可能希望将其拆分。

答案 6 :(得分:2)

另请注意,Java专门引入了静态导入:(http://en.wikipedia.org/wiki/Static_import

  

静态导入是一项介绍的功能   在Java编程语言中   成员(字段和方法)定义   在类中作为要使用的公共静态   在Java代码中没有指定   定义字段的类。   这个功能被引入了   版本5.0中的语言。

     

该功能提供了类型安全   包含常量的机制   代码,而不必参考   最初定义的类   领域。它也有助于弃用   创造常数的做法   interface:只有一个接口   定义常量然后编写一个类   实现该接口,即   被认为是不当使用   接口[1]。

     

该机制可用于参考   个别成员:

 import static java.lang.Math.PI;
 import static java.lang.Math.pow;
  

或类的所有静态成员:

 import static java.lang.Math.*;

答案 7 :(得分:2)

虽然我同意这听起来像是一个合理的解决方案的观点(正如其他人已经说过的那样),但您可能想要考虑的一件事是,从设计的角度来看,为什么您只是为了“效用”目的而拥有一个课程。这些函数在整个系统中是否真正通用,或者它们是否与架构中某些特定对象类相关。

只要您考虑过这一点,我认为您的解决方案没有问题。

答案 8 :(得分:1)

Java SDK中的Collections类只有静态成员。

所以,你去,只要你有正确的理由 - 这不是一个糟糕的设计

答案 9 :(得分:1)

实用程序方法通常只放在只有静态方法的类中(如StringUtils。)全局常量也放在它们自己的类中,以便它们可以由其余代码导入(public final static属性。)

两种用法都非常常见,并且具有私有默认构造函数以防止它们被实例化。声明类final可以防止尝试覆盖静态方法的错误。

如果static member variables你并不是指全局常量,那么你可能希望将访问这些变量的方法放在它们自己的类中。 在这种情况下,您能否详细说明这些变量在代码中的作用?

答案 10 :(得分:1)

这通常是如何设计实用程序类的,并且没有任何错误。着名的例子包括o.a.c.l.StringUtilso.a.c.d.DbUtilso.s.w.b.ServletRequestUtils等。

答案 11 :(得分:1)

根据面向对象设计的严格解释,实用程序类是值得避免的。

问题在于,如果你遵循严格的解释,那么你需要强制你的类进入某种排序对象,以便完成很多事情。

即使是Java设计人员也会创建实用程序类(java.lang.Math)。

您的选择是:

double distance = Math.sqrt(x*x + y*y);  //using static utility class

VS

RootCalculator mySquareRooter = new SquareRootCalculator();
mySquareRooter.setValueToRoot(x*x + y*y);
double distance;
try{
   distance = mySquareRooter.getRoot();
}
catch InvalidParameterException ......yadda yadda yadda.      

即使我们要避免使用冗长的方法,我们仍然可以得到:

Mathemetician myMathD00d = new Mathemetician()
double distance = myMathD00d.sqrt(...);

在这个例子中,.sqrt()仍然是静态的,那么首先创建对象的重点是什么?

答案是,当你的另一个选择是创建某种对实例变量没有或很少使用的人工“工人”类时,创建实用程序类。

答案 12 :(得分:1)

此链接http://java.dzone.com/articles/why-static-bad-and-how-avoid似乎违背了大部分答案。即使它不包含成员变量(即没有状态),静态类仍然可能是一个坏主意,因为它不能被模拟或扩展(子类),所以它正在击败OO的一些原则

答案 13 :(得分:0)

我不会担心包含静态方法的实用程序类。

但是,静态成员本质上是全局数据,应该避免使用。如果它们用于缓存静态方法的结果等,它们可能是可以接受的,但如果它们被用作可能导致各种问题的“真实”数据,例如隐藏的依赖性和设置测试的困难。

答案 14 :(得分:0)

来自TSLint’s docs

来自 Java 风格的 OO 语言的用户可以将他们的实用程序函数包装在一个额外的类中,而不是将它们放在顶层。

最好的方法是使用常量,就像这样:

export const Util = {
    print (data: string): void {
        console.log(data)
    }
}

此规则的错误代码示例:

class EmptyClass {}

class ConstructorOnly {
  constructor() {
    foo();
  }
}

// Use an object instead:
class StaticOnly {
  static version = 42;
  static hello() {
    console.log('Hello, world!');
  }
}

此规则的正确代码示例:

class EmptyClass extends SuperClass {}

class ParameterProperties {
  constructor(public name: string) {}
}

const StaticOnly = {
  version: 42,
  hello() {
    console.log('Hello, world!');
  },
};