【问题标题】:Why can't a Java class be declared as static?为什么不能将 Java 类声明为静态?
【发布时间】:2011-01-23 12:46:32
【问题描述】:

我试图找出为什么不能将类创建为静态的?喜欢:

public static class Qwert{

    public static void main(String args[]){

        int x = 12;
        while(x<12){
            x--;
        }
        System.out.println(" the X value is : "+ x);
    }
}

【问题讨论】:

    标签: java oop class


    【解决方案1】:

    在 Java 中,static 关键字通常将方法或字段标记为不是每个类的实例存在一次,而是永远存在一次。一个类无论如何都存在一次,因此实际上,所有类都是“静态”的,所有对象都是类的实例。

    static 确实对 inner 类有意义,这是完全不同的:通常内部类实例可以访问与其绑定的外部类实例的成员,但如果内部类是static,它没有这样的引用,可以在没有外部类的实例的情况下实例化。也许您在某个地方看到了它,然后尝试在没有意义的顶级类上使用它。

    或者您可能在其他语言中看到它,例如 C#,其语法与 Java 非常相似。

    (有一次我不明白为什么外部类实例没有被垃圾回收——这是因为我在别处保留了对其内部类实例之一的引用,而内部类不是 @ 987654324@ 所以有一个外部类实例的引用。所以默认情况下,我现在创建内部类static。)

    【讨论】:

    • 非常准确。默认情况下,内部类不是静态的,也就是说,具有嵌套类的类的每个实例都有自己的嵌套类副本。这就是你可以在类中引用“this”的方式,以及为什么你不能声明静态方法或字段,这没有任何意义,因为外部类的每个实例都有自己的副本。 “静态”嵌套类(根据定义是真正的“内部”类)意味着该类只有一个副本,这更像是一个常规类。我一直认为这些嵌套类的语义非常复杂。
    • 我也歪曲了关于每个实例存在一次的非静态方法的真相,从内存的角度来看,它们实际上并没有。我只是提出一个概念性观点。
    • @jeff,就该类的对象实例化而言,静态声明的内部类和非静态类之间有什么区别?是否有某种方式,您只能从静态内部类实例化一个对象,并且可以从非静态内部类实例化多个对象?是吗?
    • 对于变量,它不是“一次”,而是每个类一次。由于一个类可以由不同的类加载器加载多个,它的静态可以存在多个,尽管在不同的命名空间中。
    • @ultrajohn 如果内部类是静态的,它只是一个在另一个类中声明的类,所以你可以正常实例化它。否则,您必须有一个外部类实例来执行此操作,因为新实例将使用其成员。完整的语法是“outerClassInstance.new InnerClass(args)”。但是如果“this”是外部类的一个实例,那么你只需要说“new InnerClass(args)”,它就会将该实例与“this”关联起来。
    【解决方案2】:

    为了防止特定类被实例化,您应该添加一个私有构造函数。这会阻止“任何其他”类创建 Qwert 类型的对象。

    例如:

        public static class Qwert{
    
    
            private Qwert() {}
    
            public static void main(String args[]){
    
                int x = 12;
                while(x<12){
                    x--;
                }
                System.out.println(" the X value is : "+ x);
            }
        }
    

    【讨论】:

    • 很好的洞察力,这可能就是他想要做的事情。
    【解决方案3】:

    我们应该将成员定义为静态的

    1. 应该对类的所有对象通用。
    2. 应该属于类并且可以通过类名访问。
    3. 应该不需要类的对象来访问它们。

    现在假设我们将外部类定义为静态并假设我们被允许这样做。这是否会为开发人员服务或为开发人员提供任何优势,或者会给开发人员和语言创建者带来歧义和复杂性?

    让我们检查一下,将外部类定义为静态是否符合我们上面定义的目的?

    1. 每个类已经对其所有对象通用,无需将其设为静态即可对其所有对象可用。
    2. 我们需要一个类名来访问其静态成员,因为这些成员是类的一部分,而外部类是包的一部分,我们可以通过编写 package_name.class_name(类似于 class_name.static_field_name)直接访问该类,所以再次,无需执行默认情况下已经存在的操作。
    3. 如果类是可见的,我们不需要任何对象来访问它,我们可以简单地编写 package_name.class_name 来访问它。根据定义,一个类是其对象的蓝图,我们创建一个类来从中创建对象(例外总是存在,例如 java.lang.Math),同样没有必要将外部类定义为静态的。

    从以上几点,我们可以说 Java 创建者不允许外部类是静态的,因为没有必要将其设为静态。允许外部类静态只会增加复杂性、歧义和重复性。阅读更多关于Why An Outer Java Class Can’t Be Static

    【讨论】:

      【解决方案4】:

      为了防止任何类通过继承或使用reflection创建Qwert的实例,您可以通过放置一个毒丸使构造函数失败:

      public class Qwert { 
      
          private Qwert() throws IllegalAccessException {
              throw new IllegalAccessException("Utility class!");
          }
      
          public static class Yuiop {
              public Yuiop() throws IllegalAccessException {
                  // generates a synthetic accessor method to super()
              }
          }
      
          public static void main(String args[]) {
              new Yuiop();
          }
      }
      

      【讨论】:

        【解决方案5】:

        这是因为当我们对组件使用 static 关键字时,该组件成为类级组件,其内存被其类占用。

        【讨论】:

          【解决方案6】:

          在 Java 中,根据定义,静态应用于类的内部组件。 “X 是静态的”在 Java 中意味着“X 与定义它的类相关联,而不是与该类的任何实例相关联”。

          “静态”一词的字面意思是“固定在内存中的一个位置”。类的每个实例共享一个静态变量或静态成员。因此使用“类变量”作为“静态变量”的同义词。这让您立即看到您不能将外部类定义为静态的。

          因此,您的类 Qwert 不能创建为静态的。除非它被归入外部类的组件中,否则有效地使其成为内部类。

          【讨论】:

            猜你喜欢
            • 2011-04-04
            • 2011-10-13
            • 2021-11-06
            • 2013-03-05
            • 1970-01-01
            • 1970-01-01
            • 2011-12-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多