关于静态构造函数,方法和字段的一些问题

时间:2010-09-14 16:01:05

标签: c# java static

我对静态成员的行为有一些疑问:

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

MyClass.myStaticField;

或者我必须先初始化MyClass:

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

2)我记得,静态字段不是垃圾收集的吗?这是一个原因,为什么我不应该实现静态方法呢?当我读到这个主题时,大多数人声称,你应该使用静态方法,你可以选择静态和非静态。

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

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

6 个答案:

答案 0 :(得分:3)

静态字段和构造函数初始化之间的区别有点复杂,因为它在框架版本之间发生了变化。 Jon做了一篇关于这个主题的深入博客文章,你应该看看。

静态字段与普通值一样被垃圾收集。也就是说,无法再访问它们时会收集它们。这可能发生在许多场景中,其中最常见的是AppDomain卸载时。静态字段特定于AppDomain所以一旦它卸载它的成员就可以收集(对于AppDomain中性类型可能不同但我不相信)。

处理静态成员是完全合法的,尽管如果你将处置值留在字段中并因此可以访问应用程序的其余部分(可能没有意识到它被处理掉)会导致一些问题。

答案 1 :(得分:1)

静态方法不能免于垃圾收集。随心所欲地使用它们。

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

答案 2 :(得分:1)

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

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

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
}

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

答案 3 :(得分:1)

你也把它标记为Java,所以有几个Java观点。

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

2)。不要将字段,静态或其他字段视为垃圾收集 - 它是收集垃圾的对象。所以如果你有:

 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引用的Another的情况下,当MyClass实例本身被垃圾收集时会发生这种情况。但是,只要MyMlass为JVM所知,x引用的OneThing仍将被引用。但是,类本身可以被垃圾收集,因此最终可能会删除x引用并将OneThing对象进行垃圾回收。

答案 4 :(得分:0)

  1. 静态构造函数/初始化程序都在同一时间发生(尽管字段根据访问时间进行初始化。)
  2. 静态方法永远不会被实例化 - 它们代表行为,而不是状态。因此他们不参与垃圾收集。
  3. 否。将调用基类的静态构造函数,但这几乎不是“问题”。
  4. 处理是什么意思? C#IDisposable?如果静态字段持有实现该接口的某个实例,则答案是肯定的。

答案 5 :(得分:0)

关于#1,无论如何,在Java中直观显而易见的是,您不需要创建类的实例来使用静态成员。它会阻止具​​有不打算实例化的类的能力(例如java.util.Collections)。

另外,你与最常见的单身人士模式存在矛盾:

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