2010-09-14 75 views
1

我对静态成员的行为的一些问题,有些问题:初始化静态字段和静态构造函数时有关静态构造函数,方法和字段

1)是否有区别?就我所知,静态字段在程序执行时被初始化。请问静态构造函数的成员的行为同样的方式,或者他们是在第一次使用初始化:

MyClass.myStaticField; 

或我必须首先初始化MyClass的:

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

2)当我这样做召回,静态字段是不是垃圾集?所以这是一个原因,为什么我不应该instanciating静态方法?当我阅读了这个主题后,大多数人声称,你应该使用静态方法,你可以在静态和非静态之间进行选择。

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

4)只是好奇心,你可以配置静态成员吗​​?

+1

你能说清楚,如果你想有一个C#,Java或比较答案。 – 2010-09-14 16:27:12

回答

1

静态方法不受垃圾回收的限制。使用他们所有你喜欢的。

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

3

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

静态字段是收集就像正常值垃圾。那就是他们在不能再被访问时被收集。这可能发生在多种情况下,其中最常见的情况是当AppDomain卸载时。静态字段是特定于AppDomain,所以一旦它卸载它的成员可以收藏(这可能是不同的AppDomain中性类型,但我不这么认为)。

这是完全合法的处置静态成员但如果你在现场留下的配置价值,因此对应用程序的其余部分访问(可能没有意识到它的配置),它可能会导致一些问题

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

作为一个澄清,静态方法可以有局部变量,这些变量在*超出范围时被*垃圾收集。 – 2010-09-14 16:15:28

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 
} 

一般而言,使用实例变量/方法时的值影响的对象的单个实例,并使用静态变量和方法时,他们没有。

+0

因此,静态{}和http://msdn.microsoft.com/en-us/library/k9x6w0hc%28VS.80%29.aspx – kofucii 2010-09-14 16:12:39

+0

之间没有区别啊,我的回答更具体到Java,因为您标记为C#和Java。抱歉。 – 2010-09-14 16:16:43

+0

在C#中,有静态构造函数。 http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx – 2010-09-14 16:17:03

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引用的另一个情况下,发生在MyClass实例本身被垃圾收集时。但是,只要MyClass被JVM知道,x引用的OneThing仍然会被引用。但是,类本身可以被垃圾回收,因此最终可能会删除x引用并且OneThing对象被垃圾收集。

0

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

加上你有最常见的单模式的矛盾:

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