代码之家  ›  专栏  ›  技术社区  ›  kofucii

关于静态构造函数、方法和字段的几个问题

  •  1
  • kofucii  · 技术社区  · 14 年前

    1) 初始化静态字段和静态构造函数时有区别吗?据我所知,静态字段是用程序执行初始化的。静态构造函数的成员行为是否相同,还是在首次使用时初始化:

    MyClass.myStaticField;
    

    或者我必须先初始化我的类:

    Myclass m = new MyClass();  // static constructor is called
    MyClass.myStaticField;      // and after that
    

    2) 我记得,静态字段不是垃圾收集的吗?所以这是我不应该实例化静态方法的原因吗?当我读到这个主题时,大多数人都声称,当你使用静态方法时,你可以在静态和非静态之间进行选择。

    3) 当您从具有静态构造函数的父类派生类时,是否有必须指出的问题?

    4) 只是好奇,你能处理静态成员吗?

    6 回复  |  直到 14 年前
        1
  •  3
  •   JaredPar    14 年前

    静态字段和构造函数初始化之间的区别有点复杂,因为框架版本之间会有所不同。乔恩写了一篇关于这个主题的深度博客文章,你应该看看。

    静态字段像普通值一样被垃圾回收。也就是说,当无法再访问它们时,它们会被收集起来。这种情况在许多情况下都可能发生,其中最常见的情况是 AppDomain 卸载。静态字段特定于 所以一旦卸载,它的成员就可以收集了(这可能不同于 应用程序域 中性类型,但我不这么认为)。

    处理静态成员是完全合法的,但是如果您将已释放的值保留在字段中,然后应用程序的其余部分可以访问它,则会导致一些问题(应用程序可能不会意识到它已被释放)

        2
  •  1
  •   Steven Sudit    14 年前

    静态字段通常不会被垃圾回收,因为它不会超出范围。但是,如果要将静态字段设置为null,则它用来引用的实例将成为垃圾回收的候选实例。您甚至可以在清空静态字段之前调用Dispose。

        3
  •  1
  •   Jeff Storey    14 年前

    静态字段和实例(非静态)字段有非常不同的含义,在决定使用哪个字段之前,理解它们是很重要的。

    静态变量或方法属于类,而不属于该类的特定实例。每个类都有一个副本(不管创建多少个实例),并且可以在没有类实例的情况下访问它。例如,

    public class MyClass {
       static int myInt = 5;
    }
    
    System.out.println(MyClass.myInt); // this prints 5
    MyClass.myInt = 10;
    System.out.println(MyClass.myInt); // this prints 10
    

    实例变量需要类的实例

    public class MyClass {
        private int myInt2;
    
        public void setMyInt2(int val) {
            myInt2 = val;
        }
    
        public int getMyInt2() {
            return myInt2;
        }
    }
    
    MyClass m1 = new MyClass();
    MyClass m2 = new MyClass();
    System.out.println(m1.getMyInt2()); // prints 0, the default value
    System.out.println(m2.getMyInt2()); // prints 0, the default value
    m1.setMyInt2(3);
    m2.setMyInt2(5);
    // each object operates on its own instance of the variable
    System.out.println(m1.getMyInt2()); // prints 3
    System.out.println(m2.getMyInt2()); // prints 5
    

    而且,没有一个 static constructor. 有构造函数和静态初始值设定项块。静态初始值设定项块写为:

    static {
       // initialize some static members here
    }
    

    通常,当值影响对象的单个实例时,使用实例变量/方法,而不影响时,则使用静态变量和方法。

        4
  •  1
  •   djna    14 年前

    您也将其标记为Java,因此有两个Java透视图。

    1) 一。在Java中没有静态构造函数的概念,相反,您可以将代码块定义为静态的,它们在类准备使用时运行—毕竟,静态字段由类的所有实例共享,因此在我们有任何工作实例之前不需要初始化。

     class MyClass {
    
            private static OneThing x = new OneThing();
            private Another y = new Another();            
     } 
    
     // some code
    
         MyClass m = new MyClass();  // creates instance of MyClass
         m = null;
    
    // no one now references that instance of MyClass
    

    你不是在垃圾收集x和y,而是在垃圾收集OneThing和其他实例。当没有对这些对象的引用时,就会发生这种情况。

    对于y引用的另一个实例,当MyClass实例本身被垃圾回收时,就会发生这种情况。但是只要JVM知道MyClass,x引用的OneThing仍然会被引用。但是,课程本身 被垃圾收集,因此最终有可能移除x引用并对OneThing对象进行垃圾收集。

        5
  •  0
  •   Kirk Woll    14 年前
    1. 静态构造函数/初始值设定项都会同时发生(尽管字段会根据访问时间进行初始化)
    2. 静态方法从不实例化——它们表示行为,而不是状态。因此它们不参与垃圾收集。
    3. 不,基类的静态构造函数将被调用,但这不是一个“问题”。
    4. 你说的处置是什么意思?我可以吗?如果静态字段包含实现该接口的某个实例,那么答案是肯定的。
        6
  •  0
  •   Mark Peters    14 年前

    关于#1,在Java中很明显,您不需要创建类的实例来使用静态成员。它将阻止一个不打算被实例化的类(例如。 java.util.Collections

    另外,你会与最常见的单例模式产生矛盾:

     public SomeSingletonClass {
         public static final SomeSingletonClass instance = new SomeSingletonClass();
         private SomeSingletonClass() {}
     }