对静态的约束

时间:2013-10-08 06:35:46

标签: java jvm

static方法只能从同一个类中调用静态方法/字段。问题:

  1. 为什么static不能使用非静态方法/字段,因为一旦调用static方法,JVM就为它创建了一个对象,可以访问类的其他部分如果JVM允许?

  2. 为什么static方法允许来自其他类的非静态方法的对象。强制限制他们只能访问static个其他类并让static访问同一类的非静态成员会产生任何差异?

5 个答案:

答案 0 :(得分:3)

以下是静态方法和字段的java语言规范。希望它能帮到你

<强> 8.3.1.1。静态字段

如果一个字段被声明为static,那么无论该类最终可以创建多少个实例(可能为零),都只存在该字段的一个化身。静态字段(有时称为类变量)在初始化类时实现(第12.4节)。

未声明为静态的字段(有时称为非静态字段)称为实例变量。每当创建一个新的类实例(第12.5节)时,就会为该类或其任何超类中声明的每个实例变量创建一个与该实例关联的新变量。

<强> 8.4.3.2。静态方法

声明为static的方法称为类方法。

在类方法的标题或正文中使用任何周围声明的类型参数的名称是编译时错误。

始终在不引用特定对象的情况下调用类方法。尝试使用关键字this(§15.8.3)或关键字super(§15.11.2)引用当前对象是编译时错误。

未声明为static的方法称为实例方法,有时也称为非静态方法。

对于一个对象,总是调用一个实例方法,该对象成为执行方法体时关键字this和super引用的当前对象。

答案 1 :(得分:3)

非静态方法有一个隐式this对象可以调用其他非静态方法

静态方法不能隐式调用非静态方法,因为它没有隐式使用的对象。没有什么可以阻止你明确使用对象来调用方法。

e.g。

class Main {
    public static void main(String... ignored) {
        new Main().nonstatic(); // calls non-static method
    }

    public void nonstatic() {
        nonstatic2(); // calls non-static object with implicit reference to "this"
    }

    public void nonstatic2() {
        staticMethod(this);
    }

    public static void staticMethod(Main main) {
        main.nonstatic3(); // static calls non-static with explicit object.
    }

    public void nonstatic3() {
    }
  

静态方法只能从同一个类中调用静态方法/字段。

如示例所示,这不是真的。

  

为什么非静态方法/字段不能用于静态,因为一旦调用静态方法,JVM就为它创建了一个对象,

JVM可以自动创建一个对象,但这不太可能有用,特别是如果对象没有默认构造函数。

  

如果JVM允许,可以访问类的其他部分吗?

它可以允许,但不应该恕我直言,因为这会更有用而不是有用。

  

为什么静态方法允许来自其他类的非静态方法的对象。

静态方法允许来自所有类的对象,而不仅仅是其他类。

  

强制限制他们只能访问其他类的静态并让静态访问同一类的非静态成员会造成任何差异吗?

区别在于你没有类的隐式实例这是静态方法的全部要点。

如果你想要一个隐式实例,你可以使用非静态方法。

答案 2 :(得分:2)

  

一旦调用静态方法,JVM就为其创建了一个对象   它

事实并非如此。可以在不创建定义静态方法的类的对象的情况下调用静态方法(记住public static void main() )。

  

为什么静态方法()允许来自非静态方法的对象   其他课程。

这是因为other classe实例可以存在,而不管是否存在定义静态方法(访问other class)的类的对象。

结帐this link以获取进一步的见解。

答案 3 :(得分:2)

为了理解为什么static方法无法调用non static方法或访问non static变量,您需要了解对象即可。

Java是一种面向对象的语言。首先定义一个,它包含状态(实例变量)和更改状态的方法(实例变量)。 但是课程不是对象。它只是用于创建对象的模板,您可以使用new关键字(创建类的实例)。  创建对象后,其变量处于初始状态,然后调用读取或更改对象状态的方法。这些变量和方法是non static,因为它们需要类的对象实例。

但是,在类中,您可以定义不读取或更改状态的方法。方法的行为完全不依赖于实例变量。 这种方法可以声明为static,这意味着运行该方法不需要该类的实例。

直接在类上调用静态方法(不引用对象):

MyClass.staticMethod();//will not read or change any state, because there is no object here

您还可以在对象上调用静态方法,但不会访问对象的状态,因为它的行为不依赖也不会更改对象的状态。致电obj.staticMethod();MyClass.staticMethod();相同:

//Create an instance of a MyClass
MyClass obj = new MyClass();

//will not read or change any state of obj. 
obj.staticMethod();

但请注意,静态方法不是完全无状态的,它们仍然可以读取或更改静态varibables的状态。

另请注意,在Java中,您无法覆盖静态方法(与Delphi不同) - 如果您认为子类需要覆盖它,请不要将方法声明为静态方法。 因此,经验法则在特殊目的实用程序类中声明静态方法,无论如何都不需要实例,例如java.lang.Math,否则 即使它没有读取或更改对象的状态,也不要将方法声明为静态,因为您可能需要稍后覆盖它。

答案 4 :(得分:1)

为什么非静态方法/字段不能用于静态,因为一旦调用静态方法,JVM就为它创建了一个对象,如果JVM允许,它可以访问类的其他部分?

如果允许静态方法访问非静态方法,这意味着,将调用实例级方法而不使用该类的实例。那么你将如何覆盖该方法?覆盖查看要调用/调用方法的对象,如果直接从静态方法调用非静态(实例)方法,则使用哪个对象调用?。

从设计角度来看 -

假设您有一个名为Dog的课程。 每只狗都吃,睡觉等。但要记住的最重要的事情是所有这些都是特定于Dog实例的。应该通过实例级方法访问每个对象的状态 - 这就是整个封装点。如果你说Dog.sleep()。哪只狗应该睡觉?