0

static方法只能调用来自同一类的静态方法/字段。问题:

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

  2. 为什么static方法允许来自其他类的非静态方法的对象。施加他们只能访问static其他类的限制并让static访问同一类的非静态成员会导致任何不同吗?

4

5 回答 5

3

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

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

例如

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 允许,哪些可以访问类的其他部分?

它可以允许,但恕我直言不应该,因为这会比有用更令人困惑。

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

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

施加限制,他们只能访问其他类的静态并让静态访问同一类的非静态成员会导致任何区别吗?

不同之处在于您没有该类的隐式实例这是静态方法的重点。

如果您想要一个隐式实例,您将使用非静态方法。

于 2013-10-08T06:54:09.150 回答
3

以下是静态方法和字段的 Java 语言规范。希望对你有帮助

8.3.1.1。静态字段

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

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

8.4.3.2。静态方法

声明为静态的方法称为类方法。

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

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

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

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

于 2013-10-08T06:43:41.337 回答
2

为了理解为什么static方法不能调用non static 方法或访问non static变量,您需要了解对象之间的区别。

Java 是一种面向对象的语言。首先,您定义一个包含状态(实例变量)的和更改状态(实例变量)的方法。但是类不是对象。它只是一个用于创建对象的模板,您可以为此使用new关键字(创建类的实例)。创建对象后,其变量处于初始状态,然后调用读取或更改对象状态的方法。这样的变量和方法non 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();

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

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

于 2013-10-08T11:35:42.090 回答
2

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

这不是真的。可以调用静态方法,而无需创建该类定义静态方法的对象(记住public static void main())。

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

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

查看此链接以获取更多见解。

于 2013-10-08T06:40:22.443 回答
1

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

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

从设计的角度来看——

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

于 2013-10-08T07:14:03.507 回答