9

我们可以通过将构造函数设为私有来限制类对象的创建。但是这个构造函数仍然可以从类中调用。有没有办法在Java中防止这种情况?

谢谢。

4

6 回答 6

14

不,没有干净的方法可以做到这一点。我真的看不出这样做的理由。因为如果构造函数是私有的,这意味着他只能从这个确切的类中的代码中调用(没有子类,或者包中的其他类),所以如果你不希望构造函数被调用,请在其上添加注释这么说的。

由于能够使用构造函数的每个人都可以删除您放置在那里以防止调用构造函数的任何措施,因此它不会产生任何实际影响。

此外,如果您需要单例,那么您可能希望构造函数至少运行一次(除非您对单例的想法是纯静态类)。

于 2010-05-23T19:09:06.170 回答
9

如果它是私有的,并且您不希望它在自己的类中被调用,那么有一种简单的方法可以防止这种情况发生:不要编写多次调用它的代码。您是该课程的作者。你为什么要编写代码来阻止你自己做一些你可以控制的事情?

它不能在课堂外调用而不诉诸反射。如果您不想在课堂上多次调用它,那么就不要这样做。为什么要编写代码来阻止您可以选择不执行的操作?

我们来复习:

我们可以通过将构造函数设为私有来限制类对象的创建。

构造函数是私有的,所以不能在类外调用,除非客户端使用反射 API 来破坏访问限制。

但是这个构造函数仍然可以从中调用。无论如何在Java中防止这种情况发生?

OP 要求防止在类中调用受限构造函数。

如果这两个陈述是正确的,请解释为什么需要有逻辑来阻止对构造函数的调用。

这是私有构造函数的典型用法:

public class Singleton
{
    private static final Singleton instance = new Singleton();

    public static void main(String[] args)
    {
        Singleton singleton = Singleton.getInstance();

        System.out.println(singleton);
    }

    private Singleton() {};

    public static Singleton getInstance() { return Singleton.instance; }

    public String toString() { return Singleton.class.getName(); }
}

我看不出不允许调用私有构造函数的意义。

于 2010-05-23T19:11:51.863 回答
6

官方的回答是否定的。如果有人可以私下访问您的课程,他可以实例化它。

但是,您可以这样做:

private static int count = 0;

private MyClass(){
    if(++count>1)throw new IllegalStateException(); //allow exactly one instantiation
}
于 2010-05-23T19:09:47.107 回答
3

不,没有办法强制执行特定类型的单个实例。正如您所描述的,您最接近的方法是将构造函数设为私有,以便只有该类中的函数才能调用它。您可以在运行时做一些事情(例如,如果您的静态实例已经存在则抛出异常),但这不会在编译时为您带来任何好处。

于 2010-05-23T19:07:41.567 回答
2

如果你正在做一个单例,枚举是最好的方法:

public enum MySingleton {
    INSTANCE;
    // add methods & stuff here
}

// Usage:
MySingleton.INSTANCE.doSomething();

JVM 保证了“单调性”——只有一个实例。

于 2010-05-23T20:43:20.580 回答
1

是的,有一个简单的方法:只需让私有构造函数抛出异常:

class MyStaticFunctions {
    private MyStaticFunctions() {
        throw new UnsupportedOperationException("do not instantiate");
    }
}

请注意,我的答案不同,因为我对问题的解释与列出的大多数其他答案略有不同。许多其他答案假设您希望该类成为单例,在这种情况下,构造函数需要仅调用一次。我假设您不想要该类的任何实例,因此应该调用构造函数 0 次。

于 2020-07-10T00:06:55.540 回答