Java中的静态类


Answers:


847

Java具有静态嵌套类,但听起来您正在寻找顶级静态类。Java无法将顶级类设为静态,但是您可以像这样模拟静态类:

  • 声明您的课程final-阻止扩展课程,因为扩展静态课程没有意义
  • 创建构造函数private-防止通过客户端代码实例化,因为实例化静态类没有任何意义
  • 创建类的所有成员和函数static-由于无法实例化该类,因此无法调用任何实例方法或无法访问实例字段
  • 请注意,编译器不会阻止您声明实例(非静态)成员。仅当您尝试调用实例成员时才会显示该问题

每个建议的简单示例:

public class TestMyStaticClass {
     public static void main(String []args){
        MyStaticClass.setMyStaticMember(5);
        System.out.println("Static value: " + MyStaticClass.getMyStaticMember());
        System.out.println("Value squared: " + MyStaticClass.squareMyStaticMember());
        // MyStaticClass x = new MyStaticClass(); // results in compile time error
     }
}

// A top-level Java class mimicking static class behavior
public final class MyStaticClass {
    private MyStaticClass () { // private constructor
        myStaticMember = 1;
    }
    private static int myStaticMember;
    public static void setMyStaticMember(int val) {
        myStaticMember = val;
    }
    public static int getMyStaticMember() {
        return myStaticMember;
    }
    public static int squareMyStaticMember() {
        return myStaticMember * myStaticMember;
    }
}

静态类有什么用?静态类的一个好用法是定义一次性的,实用程序和/或库类,在这些类中实例化是没有意义的。一个很好的例子是Math类,它包含一些数学常数,例如PI和E,并且仅提供数学计算。在这种情况下,需要实例化将是不必要且令人困惑的。请参阅Math类和源代码。请注意,它是,final并且其所有成员均为static。如果Java允许声明顶级类,static则Math类确实是静态的。


34
Foostatic方法的类与static class Foo
craigb 2014年

12
@Evorlor:如果将一个类声明为final,则其方法将自动(有效)为final。这是因为final类不能被子类化,因此其方法不能被覆盖(即,实际上是final)。 docs.oracle.com/javase/tutorial/java/IandI/final.html
jwayne 2015年

30
这个答案也许解决了OP的含义,但是(目前)它没有解释Java静态类,因此根本无法回答问题!对于来到这里试图弄清静态类在Java中意味着什么的人们来说,这是非常糟糕的。
汤姆(Tom)

12
@JBoy:Java中有一个“静态类”之类的东西,这就是问题所在,但是这个答案根本无法解释。相反,它解释了如何在Java中模拟答案称为“静态类”的内容-但这不是 Java中的“静态类”!(也许这是其他一些语言中的“静态类”,但是来这里学习Java静态类的人会被误导和迷惑。)
汤姆

4
您应该明确提到private MyStaticClass(){//私有构造函数myStaticMember = 1; }将完全没有效果,因为不会调用构造函数。但这不是重点。我仍然对Java中的静态内部类的效用及其实用性或附加值感到困惑。
摩尔多瓦人

315

好吧,Java有“静态嵌套类”,但是如果您来自哪里,它们与C#的静态类根本不一样。静态嵌套类只是一个没有隐式引用外部类实例的类。

静态嵌套类可以具有实例方法和静态方法。

Java中没有顶级静态类。


12
在Java中,为什么静态嵌套类允许实例方法?在此类中实例方法有什么用?
极客

19
@Geek:你读了我的答案吗?仔细阅读第二句话。您为什么希望拥有静态类的实例方法?毕竟,您可以创建它们的实例。
乔恩·斯基特

17
@Geek:是的,完全可以。您对静态类是实用程序类的“理解”基本上是错误的。这根本不是Java中的静态类的意思。
乔恩·斯基特

14
@Geek:是的。就像我在回答中所写的那样:“静态嵌套类只是一个没有隐式引用外部类实例的类。”
乔恩·斯基特

6
@KhurramAli:你的意思是暗示?考虑到您在声明它们时不使用关键字,它们肯定不是显式静态的static。它们是隐式静态的,因为您不需要引用其他任何东西即可构造一个。就我个人而言,无论如何,对于嵌套类而言,静态/非静态术语有点奇怪……我认为谈论行为是更简单的。
乔恩·斯基特

157

有一个静态嵌套类,此[static nested]类不需要封闭类的实例即可实例化自身。

这些类[静态嵌套类]只能访问封闭类的静态成员[因为它没有对封闭类实例的引用...]

代码示例:

public class Test { 
  class A { } 
  static class B { }
  public static void main(String[] args) { 
    /*will fail - compilation error, you need an instance of Test to instantiate A*/
    A a = new A(); 
    /*will compile successfully, not instance of Test is needed to instantiate B */
    B b = new B(); 
  }
}

1
那么可以说我们可以使用内部静态类来实例化它们而无需将其公开吗?
摩尔多瓦人

@moldovean我们使用内部静态类以便从静态上下文(例如main)实例化它们。我认为这与可见度无关。
迈克尔·多斯特

2
@moldovean静态/非静态与可见性正交。您可以使用静态或非静态的任何可见性。关键是,为了创建内部类,您是否需要封闭类的实例?
阿米特

103

是的,Java中有一个静态嵌套类。当您声明一个嵌套类为静态时,它会自动成为一个独立的类,无需实例化它所属的外部类就可以实例化。

例:

public class A
{

 public static class B
 {
 }
}

因为class B声明为静态,所以您可以显式实例化为:

B b = new B();

注意,如果class B不是为了使其独立而声明为静态的,则实例对象调用将如下所示:

A a= new A();
B b = a.new B();

7
请注意,您可以定期实例化非静态类,就像B b = new B();您尝试从Class A本身实例化它一样。
穆罕默德·里法(Muhammed Refaat)

33

当a中的成员class声明为static.. 时会发生什么情况?无需实例化即可访问该成员class。因此,使外部类(顶级类)static没有意义。因此,这是不允许的。

但是您可以将内部类设置为静态类(因为它是顶级类的成员)。然后,可以在不实例化顶级类的情况下访问该类。考虑以下示例。

public class A {
    public static class B {

    }
}

现在,在另一个类中CB无需创建class实例即可访问class A

public class C {
    A.B ab = new A.B();
}

static类也可以有non-static成员。只有该类是静态的。

但是如果static从类中删除了关键字B,那么如果没有创建实例的话不能直接访问它A

public class C {
    A a = new A();
    A.B ab = a. new B();
}

但是我们不能staticnon-static内部类中有成员。


我们可以实例化一个静态类还是有意义的?
Supun Wijerathne

6
与其他语言不同,static在Java中只有一个含义。如果某事物static在类中,则意味着可以在不实例化该类的情况下访问该事物。这并不是说关于创建实例或不..什么
拉梅什-X

抱歉stackoverflow!在这种情况下,我不可避免地要说谢谢Ramesh-X!您涵盖了几乎所有我想知道的有关静态内部类和内部类的内容。
Moldovean

您不能“将内部类设置为静态”。这是一个矛盾。嵌套类是内部的或静态的。
user207421 '19

13

看到这是Google上“静态类java”的最佳结果,最好的答案不在这里,我想我会添加它。我将OP的问题解释为与C#中的静态类有关,C#中的静态类在Java世界中被称为单例。对于那些不知道的人,可以在C#中将“ static”关键字应用于类声明,这意味着无法实例化结果类。

摘自Joshua Bloch撰写的“ Effective Java-Second Edition”(被广泛认为是目前可用的最佳Java样式指南之一):

从1.5版开始,存在第三种实现单例的方法。只需使用一个元素创建一个枚举类型:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

此方法在功能上等效于公共领域方法,除了它更简洁,免费提供序列化机制之外,甚至在面对复杂的序列化或反射攻击时,也提供了防止多重实例化的明确保证。尽管此方法尚未广泛采用,但单元素枚举类型是实现单例的最佳方法。(强调作者的)

约书亚·布洛赫(2008-05-08)。有效的Java(Java系列)(第18页)。培生教育。

我认为实施和辩解很容易说明。


6
实现Singleton的好方法。不幸的是,问题不在于单例,而在于静态类
David SN

1
Java对“ static”关键字具有相当独特的解释。好像OP来自C#,其中“静态类”等效于Java中的单例。我已经更新了答案,以使对该问题的解释更加清楚。
Bennet Huber

1
AC#静态类不是Singleton。Singleton实例是一个对象,可以实现一个接口,这意味着它可以参与依赖注入并可以被模拟。AC#静态类无法实现接口或以任何方式进行注入,并且非常接近一堆C函数,并且当然允许使用扩展方法。
Novaterata'6

13

Java中的类可以是静态的吗?

答案是肯定的,我们可以在java中拥有静态类。在Java中,我们有静态实例变量静态方法静态块。也可以在Java中将类设为静态。

在Java中,我们无法使顶级(外部)类静态。只有嵌套的类可以是静态的。

静态嵌套类与非静态嵌套类

1)嵌套静态类不需要外部类的引用,但是非静态嵌套类或内部类需要外部类的引用。

2)内部类(或非静态嵌套类)可以访问外部类的静态和非静态成员。静态类无法访问Outer类的非静态成员。它只能访问Outer类的静态成员。

参见此处:https : //docs.oracle.com/javase/tutorial/java/javaOO/nested.html


内部的“非静态”类也不能声明静态字段或方法
Cat.Cat先生


2

简而言之,Java支持将一个类的声明仅对内部类声明为静态,而不对顶级类声明为静态。

顶级类:一个Java项目在每个Java源文件中可以包含多个顶级类,其中一个类以文件名命名。顶级类前面只允许使用三个选项或关键字: public,abstract和final

内部类:顶级类内部的类称为内部类,这基本上是嵌套类的概念。内部类可以是静态的。使内部类静态化的想法是利用实例化内部类的对象而不实例化顶级类的对象的优势。这与静态方法和变量在顶级类内部工作的方式完全相同。

因此,Java支持内部类级别的静态类(在嵌套类中)

而且Java不支持顶级类的静态类。

我希望这可以为该问题提供一个更简单的解决方案,以便对Java中的静态类有基本的了解。



0

Java具有与类关联的静态方法(例如,java.lang.Math仅具有静态方法),但类本身不是静态的。


0

除非它是内部类,否则不能将static关键字与类一起使用。静态内部类是嵌套类,它是外部类的静态成员。使用其他静态成员可以访问它而无需实例化外部类。就像静态成员一样,静态嵌套类无法访问外部类的实例变量和方法。

public class Outer {
   static class Nested_Demo {
      public void my_method() {
          System.out.println("This is my nested class");
      }
   }
public static void main(String args[]) {
      Outer.Nested_Demo nested = new Outer.Nested_Demo();
      nested.my_method();
   }
}

static除非它是嵌套类,否则不能将关键字与类一起使用。“静态内部”在术语上是矛盾的
user207421 '19

0

静态方法意味着可以访问它而无需创建类的对象,这与public不同:

public class MyClass {
   // Static method
   static void myStaticMethod() {
      System.out.println("Static methods can be called without creating objects");
   }

  // Public method
  public void myPublicMethod() {
      System.out.println("Public methods must be called by creating objects");
   }

  // Main method
  public static void main(String[ ] args) {
      myStaticMethod(); // Call the static method
    // myPublicMethod(); This would output an error

    MyClass myObj = new MyClass(); // Create an object of MyClass
    myObj.myPublicMethod(); // Call the public method
  }
}

不回答问题。
user207421 '19

-1

所有的答案都很好,但是我没有看到对java.util.Collections的引用,该引用使用大量的静态内部类作为其静态因子方法。因此添加相同。

从java.util.Collections中添加一个示例,该示例具有多个静态内部类。内部类对于将需要通过外部类访问的代码进行分组很有用。

/**
 * @serial include
 */
static class UnmodifiableSet<E> extends UnmodifiableCollection<E>
                             implements Set<E>, Serializable {
    private static final long serialVersionUID = -9215047833775013803L;

    UnmodifiableSet(Set<? extends E> s)     {super(s);}
    public boolean equals(Object o) {return o == this || c.equals(o);}
    public int hashCode()           {return c.hashCode();}
}

这是java.util.Collections类中的静态因子方法

public static <T> Set<T> unmodifiableSet(Set<? extends T> s) {
    return new UnmodifiableSet<>(s);
}


没有收到您的评论吗?你能详细说明吗?试图了解您的评论。
杰·拉杰普特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.