Java中的静态类

3
如何在Java中声明静态类?Eclipse提示我将“static”从声明中移除。
static public class Constants {
6个回答

7

首先回答你的问题:

只有嵌套类可以声明为静态。顶级类不能声明为静态。

其次,内部类是一种未显式声明为静态的嵌套类。请参见Java语言规范。因此,与此处某些答案相反,内部类不能是静态的。

引用规范中的一个例子:

class HasStatic{
    static int j = 100;
}
class Outer{
    class Inner extends HasStatic{
        static final int x = 3; // ok - compile-time constant
        static int y = 4; // compile-time error, an inner class
    }
    static class NestedButNotInner{
        static int z = 5; // ok, not an inner class
    }
    interface NeverInner{}  // interfaces are never inner
}

4
+1 是为了不混淆内部类和嵌套类。这是我非常讨厌的一件事。 :-) - C. K. Young
如果我理解正确,嵌套类可以是静态的或非静态的。嵌套接口、枚举和注解都是隐式静态的。 - emory
除非你在谈论Java 1.1,我记得它使用“内部类”来指代我们现在称之为嵌套类的概念。另外还有一点是,你可以在静态类中拥有一个内部类,在这种情况下就不会有外部的this - Tom Hawtin - tackline

1
如果你所说的“静态”是指“只能有静态成员”,那在Java中是不存在这样的东西的。
内部类(仅限于它们)可以是静态的,但这是一个不同的概念。内部静态类仍然可以拥有实例成员。

仅内部类可以是静态的。 - Thilo
2
@Thilo,我希望你在说"inner"时指的是"nested"。因为在规范中,"inner"有不同的意思。只有"nested"类可以是静态的。非静态的嵌套类被称为内部类。 - naikus
看我的评论给Thilo。内部类是嵌套类,声明为静态的。所以如果它们被声明为静态的话,你就不能称之为内部类了 :) - naikus
1
@naikus: +1 确实,内部类需要外部实例,因此它们在定义上是非静态的。换句话说,内部类是嵌套类的一个子集,也就是那些非静态的类。 - C. K. Young
@naikus,@Chris 感谢对术语的评论:我只是想说 Trevor 想做的是不可能的,并没有深入解释整个 "内部类" 概念(无论如何与问题无关)。 - Nikita Rybak

0

正如其他评论中已经告诉你的一样,类不能被声明为静态的。然而,对于这个问题有一些替代方案。

最简单的一个是在所有成员变量和方法前加上static修饰符。这基本上实现了你想要的效果。

稍微复杂一点的替代方案是将类设计为单例模式。通过使用私有构造函数和instanceOf()方法(或者只是一个枚举),你可以只有一个该类的实例。在语义和语法上,你将该实例视为特定类的普通实例,但你只能拥有一个该类的实例,通过SomeObject.instanceOf()方法或者在枚举实现中使用SomeObject.INSTANCE进行检索。

通常情况下,我们使用枚举来实现这个功能,除非你需要扩展另一个类。

关于单例模式的更详细信息,请访问下面的链接。

Java设计模式 - 单例模式


0

Eclipse正确地报错了,你的代码无法编译,因为顶层类不能声明为静态。

你需要先理解什么是静态类。

静态类:

只有成员类和嵌套顶层类可以被定义为静态,顶层类不能声明为静态。

当你想要在不显式委托的情况下使用包含类的变量和方法时,你声明成员类。当你声明一个成员类时,你只能在声明该成员类的外部类对象的上下文中实例化该成员类。如果你想要移除这个限制,你可以将成员类声明为静态类。当你用static修饰符声明一个成员类时,它就成为了一个嵌套顶层类,并且可以像上面解释的普通顶层类一样使用。

嵌套顶层类是带有static修饰符的成员类。嵌套顶层类与任何其他顶层类一样,只是它在另一个类或接口内声明。嵌套顶层类通常用作一种方便的方式来组织相关的类,而不创建新的包。

还要查看在Java中何时使用静态类、变量和方法


0

在Java中,没有直接等价于C#的静态类,但我认为最接近的是一个空枚举。一开始可能觉得很奇怪,但仔细思考后就会明白其中的道理。在Java中,枚举(与C#不同)本质上是一组实现相同抽象基类和接口的单例实例。在Java中创建普通的单例对象的最快、最安全的方法如下:

enum Foo {
    INSTANCE;
    public Bar doSomething(Baz baz) {
        return Bar.fromBaz(baz); // yadda yadda
    }
}

所以,既然我们正在处理单例集合,那么有一个空集是有意义的。而一个空集意味着没有实例存在。这在概念上与C#中的静态类是相同的。
 enum MyUtilities {
    ;
    static Bar doSomething(Baz baz) {
         return Bar.fromBaz(baz); // yadda yadda
    }
    static final String SOME_CONSTANT = "QUX";
 }

这很棒,因为你不会因为难以测试的私有构造函数而失去测试覆盖率,而且代码比一个带有空私有构造函数的最终类更清晰。
现在,如果静态类都是为了在一个单一接口上工作,并且你对该接口有控制权,那么你应该在该接口本身上实现静态方法(这是在C#中无法做到的)。

-2
所有顶级类都是隐式的静态类,这意味着它们可以被任何人访问。因此,只有将内部类设为可选的静态类才有意义。

2
这些都是不正确的。静态并不意味着“可以被每个人访问”,也不是所有的顶级类都可以被每个人访问。而且结论并不从前提中得出。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接