什么是“静态”?

时间:2009-05-27 01:33:25

标签: java static

我开始用Java编程。

public static void main(String[]args)

一本书说我应该在这种情况下使用静态,但是没有明确说明为什么我应该或它意味着什么。

你能澄清一下吗?

7 个答案:

答案 0 :(得分:23)

static的概念与某个东西是某个类还是某个对象(实例)的一部分有关。

对于main方法声明为static的情况,它表示main方法是一个类方法 - 一个属于类的方法,而不是一个对象的一部分。这意味着另一个类可以通过引用ClassName.method来调用另一个类的类方法。例如,调用MyClass的run方法将通过以下方式完成:

MyClass.main(new String[]{"parameter1", "parameter2"});

另一方面,没有static修饰符的方法或字段意味着它是对象的一部分(或者也称为“实例”)而不是类的一部分。它由方法或字段所属的特定对象的名称引用,而不是类名:

MyClass c1 = new MyClass();
c1.getInfo()     // "getInfo" is an instance method of the object "c1"

由于每个实例可能具有不同的值,因此不同对象中具有相同名称的方法或字段的值不一定必须相同:

MyClass c1 = getAnotherInstance();
MyClass c2 = getAnotherInstance();

c1.value     // The field "value" for "c1" contains 10.
c2.value     // The field "value" for "c2" contains 12.
             // Because "c1" and "c2" are different instances, and 
             // "value" is an instance field, they can contain different
             // values.

结合实例和类变量的两个概念。假设我们声明一个包含实例和类变量和方法的新类:

class AnotherClass {
    private int instanceVariable;
    private static int classVariable = 42;

    public int getInstanceVariable() {
        return instanceVariable;
    }

    public static int getClassVariable() {
        return classVariable;
    }

    public AnotherClass(int i) {
        instanceVariable = i;
    }
}

上面的类有一个实例变量instanceVariable,以及一个用classVariable修饰符声明的类变量static。同样,有一个实例和类方法来检索值。

实例的构造函数接受一个值以作为参数分配给实例变量。类变量初始化为42并且永远不会更改。

让我们实际使用上面的课程,看看会发生什么:

AnotherClass ac1 = new AnotherClass(10);

ac1.getInstanceVariable();             // Returns "10"
AnotherClass.getClassVariable();       // Returns "42"

请注意调用类和实例方法的不同方法。它们通过名称AnotherClass引用类的方式,或名称ac1引用的实例。让我们进一步看看方法的行为差异:

AnotherClass ac1 = new AnotherClass(10);
AnotherClass ac2 = new AnotherClass(20);

ac1.getInstanceVariable();             // Returns "10"
AnotherClass.getClassVariable();       // Returns "42"
ac2.getInstanceVariable();             // Returns "20"
AnotherClass.getClassVariable();       // Returns "42"

可以看出,实例变量是由对象(或“实例”)持有的变量,因此对于该特定实例是唯一的,在此示例中是ac1和{引用的对象{1}}。

另一方面,类变量仅对整个类是唯一的。为了更好地理解这一点,让我们为ac2添加一个新方法:

AnotherClass

然后,运行以下命令:

public int getClassVariableFromInstance() {
    return classVariable;
}

尽管AnotherClass ac1 = new AnotherClass(10); AnotherClass ac2 = new AnotherClass(20); ac1.getInstanceVariable(); // Returns "10" ac1.getClassVariableFromInstance(); // Returns "42" ac2.getInstanceVariable(); // Returns "20" ac2.getClassVariableFromInstance(); // Returns "42" 是一个实例方法,通过引用实例getClassVariableFromInstanceac1可以看出,它们都返回相同的值,ac2 。这是因为在两个实例方法中,它们引用类方法42,它对于类是唯一的,而不是对实例的引用 - 对于类{{1},只有classVariable的单个副本}}

我希望有些内容可以澄清classVariable修饰符的用途。

来自Sun的

The Java Tutorials有一个名为Understanding Instance and Class Members的部分,它也涉及两种类型的变量和方法。

答案 1 :(得分:11)

请参阅Wikipedia

上的详细说明

例如,请注意在Math类中,您可以说

之类的内容
Math.Abs(x);

不必说

Math m = new Math();

这些是静态方法,因为您不需要实例。实例方法是那些要求您拥有类实例的方法。

Employee e = new Employee();
e.Terminate();

答案 2 :(得分:2)

静态方法是适用于整个类的方法,而不是任何特定成员。 .goExtinct()将是一个整体鸭群的方法,而不是任何特定的鸭子。 main是public和static,因为它必须始终可用,并且它不是任何特定类的一部分。

答案 3 :(得分:1)

通常,您必须拥有一个对象,一个类的实例,以便在其上调用方法,至少有两个原因:

  1. 它取决于哪个类实现被调用方法的对象。例如,如果你有一个子类的实例,那么将调用子类中的方法,即使调用该方法的代码是相同的。
  2. 对象通常具有内部状态(字段),方法可以参考。如果没有对象实例,则不起作用。
  3. 通过调用类'constructor:

    来创建对象实例
    MyObject a = new MyObject();
    

    静态方法是未附加到对象实例的方法。可以通过命名类来调用它们。因此他们

    1. 无法动态调度到子类(这就是为什么你得到warning when you try to call it on object instances,这只是令人困惑的语法)
    2. 他们cannot refer to instance state(非静态字段和其他非静态方法)。
    3. 许多人认为静态方法是一种糟糕的设计模式,并建议不要使用它们(public static void main除外)查找替代的单例实例模式。

答案 4 :(得分:1)

在这种特殊情况下,main方法必须是静态的,因为JVM将开始加载类和创建对象的方式。当您启动Java程序时,JVM将查找传递给它的类的定义并加载它。因此java MyClass将导致加载MyClass类的定义。

根据定义,Java程序将在作为最初加载的类传递给JVM的类的main()方法中开始执行。此时,没有创建MyClass类型的实例(对象),因此main方法必须是静态的,以允许开始执行程序。

如果要查看在执行Java程序期间正在加载哪些类,可以使用-verbose:class命令行选项。

答案 5 :(得分:0)

在任何面向对象的编程语言(如Java或C ++)中,您创建的类在最基本的级别上类似于建筑物的BluePrints。您可以查看蓝图并确定各种组件的连接方式,但实际上并不能存在。类和对象也是一样的。类是蓝图,您创建一个名为Object的类的实例。对于相同的蓝图,您可以拥有多个建筑物,对于一个类别,您可以拥有多个对象。 Object是类的实例。可以在Object或类的实例上调用类中的每个方法,而对于调用静态方法,您实际上不需要实例,可以直接调用ClassName.method()而无需实际创建类的实例。

答案 6 :(得分:0)

有时您会想要定义一个将独立于该类的任何对象使用的类成员。通常,只能与类的对象一起访问类成员。但是,可以创建一个可以单独使用的成员,而无需引用特定实例。要创建此类成员,请在其声明前面加上关键字static。当成员声明为static时,可以在创建其类的任何对象之前访问它,而不引用任何对象。您可以将方法和变量声明为静态。静态成员最常见的例子是main()。 main()声明为static 因为必须在任何对象存在之前调用它。 两种类型的静态成员是静态字段和静态方法:

Static field:

使用static关键字声明的字段,如下所示:

private static int ballCount:

static关键字的位置可以与可见性关键字(私有和公共,以及受保护)的位置互换。因此,以下陈述也适用:

static private int ballCount;

作为惯例,大多数程序员倾向于将可见性关键字放在首位。

静态字段的值在类的所有实例中都是相同的。换句话说,如果一个类有一个名为CompanyName的静态字段,那么从该类创建的所有对象将具有相同的CompanyName值。

首次加载类时,会创建并初始化静态字段。当引用类的静态成员或创建类的实例时(以先到者为准),就会发生这种情况。

Static method: 

使用static关键字声明的方法。与静态字段一样,静态方法与类本身相关联,而不是与从类创建的任何特定对象相关联。因此,在使用类定义的静态方法之前,不必从类创建对象。

最着名的静态方法是main,由Java运行时调用以启动应用程序。 main方法必须是静态的,这意味着默认情况下应用程序在静态上下文中运行。

使用静态方法的基本规则之一是您无法从静态方法访问非静态方法或字段,因为静态方法没有用于引用实例方法或字段的类的实例