Java 助手/实用程序类应该是抽象的吗?

Java 助手/实用程序类应该是抽象的吗?,java,abstract-class,Java,Abstract Class,我经常发现自己将常见行为从类中提取到只包含一组静态方法的helper/utility类中。我经常想知道是否应该将这些类声明为抽象类,因为我真的想不出一个有效的理由来实例化它们 将此类类声明为抽象类的利弊是什么 public [abstract] class Utilities{ public static String getSomeData(){ return "someData"; } public static void doSomethingToObj

我经常发现自己将常见行为从类中提取到只包含一组静态方法的helper/utility类中。我经常想知道是否应该将这些类声明为抽象类,因为我真的想不出一个有效的理由来实例化它们

将此类类声明为抽象类的利弊是什么

public [abstract] class Utilities{

   public static String getSomeData(){
       return "someData";
   }

   public static void doSomethingToObject(Object arg0){
   }
}

通过将这些类声明为抽象类,实际上是在向其他编码人员表明您打算从中派生这些类。真的,你是对的,没有太大的区别,但是这里的语义实际上更多的是关于其他人对你的代码的解释。

不,但是如果你的语言支持它,有一个强有力的论点,在大多数情况下,它们应该(可以)声明为“静态”。。。Static告诉编译器它们不能被实例化,并且其中的所有方法都必须是静态的


抽象用于具有基于实例的实现细节的类,这些细节将由派生类的实例使用

您可以只声明一个不做任何事情的私有构造函数


将类声明为“abstract”的问题是,abstract关键字通常意味着该类将被子类化和扩展。这绝对不是您想要的。

不要麻烦将它们抽象化,而是包含一个私有的无参数构造函数,以防止它们被实例化



public final class Utility
{
    private Utility(){}

    public static void doSomethingUseful()
    {
        ...
    }
}

对那些感兴趣的人来说,比较点是:在C#中,您可以将类声明为静态的,使其以编译的形式抽象和密封(Java的final),并且根本没有任何实例构造函数。这也使得声明该类型的参数、变量、数组等成为编译时错误。方便。

助手/实用程序方法很好。不要担心将它们添加到应用程序或框架内的库中。我所看到的大多数框架都以多种形式使用它们


这就是说,如果你真的想巧妙地处理它们,你应该研究C#3.0。使用扩展方法将使您的实用程序在您的框架中更像是一个“整体”的部分,这似乎是您通过考虑将它们抽象化而试图做的事情。更不用说扩展方法了,写起来很有趣

有人提到,在C#3.0中,您可以通过扩展方法来实现这一点。我不是一个C#家伙,在1.5/2.0天做了一些,但从那以后就没有使用过。基于非常粗略的理解,我认为在java中可以通过静态导入实现类似的功能。我意识到这完全不是一回事,但如果目标只是让这些实用方法对调用类来说更“本地”(因为没有更好的术语),我认为它会奏效。假设我在原始问题中声明的实用程序类

import static Utilities.getSomeData;

public class Consumer {

    public void doSomething(){

        String data =  getSomeData();
    }

}

正如其他人所说的,创建一个私有参数较少的构造函数。除了类本身,没有人可以创建它的实例

其他人已经展示了它是如何用其他语言完成的,下面是如何在下一个C++版本中实现的,如何使类不可例示:

struct Utility { 
    static void doSomething() { /* ... */ } 
    Utility() = delete; 
};

我没有将实用程序类声明为抽象类,而是将它们声明为最终类,并将构造函数设置为私有类。这样,它们就不能被子类化,也不能被实例化



public final class Utility
{
    private Utility(){}

    public static void doSomethingUseful()
    {
        ...
    }
}

我将在私有构造函数之外添加更多步骤:

public class Foo {
   // non-instantiable class
   private Foo() { throw new AssertionError(); }
}
抛出
AssertionError
可以防止同一类中的方法实例化该类(当然,他们可以尝试)。这通常不是问题,但在团队环境中,你永远不知道有人会做什么

关于“abstract”关键字,我注意到在许多实例中都有子类化的实用程序类:

public class CoreUtils { ... }
public class WebUtils extends CoreUtils { ... }

public class Foo { ... WebUtils.someMethodInCoreUtils() ... }
我相信这样做是为了让人们不必记住要包含哪个实用程序类。这有什么坏处吗?这是反模式吗

问候,,
LES

我可以提供一些建设性的建议吗

如果你经常这样做,你会遇到两个问题

首先,接受参数的静态方法通常应该是作为该参数的对象的一部分。我意识到这对像字符串这样的对象没有帮助,但是如果它接受您定义的对象,您几乎可以肯定地通过将您的助手作为该对象的方法来改进该对象

如果它接受所有本机值,那么您可能可以定义一个它作为方法的对象。查看是否可以找到这些本机值的任何分组,并将它们作为对象分组。如果你尝试一下,你会发现这个小东西还有很多其他用途,在你意识到之前,它会非常有用

另一件事,如果你有一个实用类,它有一堆半相关的静态方法和静态变量,你几乎总是希望它是一个单例。我通过反复试验发现了这一点,但是当你发现你需要不止1个(最终你会),把一个单态变成一个多态(?)比把一个静态类变成一个多态要容易得多(好吧,我现在正在编词)


祝你好运。这些东西对我来说基本上是反复试验的——不过我在5年前就发现了,而且我从来没有发现过一个我后悔没有静态类/方法的实例。

我认为最好用一个私有的无参数构造函数来声明实用程序类final。此外,该类的所有成员都应该是静态的

在一条语句中完成所有这些操作的简单方法是使用:


如果您使用
@UtilityClass
注释,您可以跳过上面示例中的静态关键字,因为Lombok会在编译过程中自动添加它们。

java类不能声明为静态的,是吗?也许我只是误解了你的观点?对不起,我是.Net的家伙没有注意到java标记。。。然后,如果java类不能被声明为静态的,那么您应该使私有的无参数ctor和所有成员都是静态的……在某些情况下,Ja