从静态方法java中引用实例变量


Line 1:  public class C { 
Line 2:      public static void main(String[] args) { 
Line 3:         // method2();
Line 4:      }
Line 5: 
Line 6:      
Line 7:      Circle c = new Circle();
Line 8:      public static void method2() { 
Line 9:          // Circle c = new Circle();
Line 10: 
Line 11:        System.out.println("What is radius "+ c.getRadius()); //compile error : non-static variable c cannot be referenced from a static context.  Why? here "c" is a instance variable. 
Line 12:     }
Line 13: 
Line 14:    
Line 15:  }
Line 16:  
Line 17:   class Circle
Line 18:  {
Line 19:    public  int getRadius()
Line 20:    {
Line 21:        return 3;
Line 22:    }
Line 23:  }

问题:在第11行,编译错误提示,非静态变量c不能从静态上下文中引用。为什么?这里"c"是一个实例变量。但是下面的代码是可以的。为什么?

如果我将第8行改为第12行

public static void method2() { 
    Circle c = new Circle();
    System.out.println("What is radius "+ c.getRadius()); 
}

或:

Circle c = new Circle();
public void method2() { 
    System.out.println("What is radius "+ c.getRadius());
}

当您使用static关键字创建方法时,它是静态方法或类方法。这意味着它对于对象的每个实例都是相同的,因此您不能从实例变量内部访问实例变量。在静态方法内部,您只能访问静态变量或调用类的静态方法。

静态成员可以在没有类实例的情况下使用,但是c变量只有在类实例化后才开始存在。编译器会检查你的代码是否可以运行,并且在实例化之前,静态方法可以被调用,但是c实例不能。

第二个块是可以的,因为这里的method2是一个实例方法,而在第一次尝试中,method2仍然是静态的。

在第一个示例中,Circle c是一个成员变量。当你的类C的一个实例被创建时,你创建了这个类的一个实例。当你调用static方法中的方法时,没有Circle c的实例。

你的第二个例子成功了,因为你在你的方法中创建了实例,并在那里调用它。

你的第三个例子工作,因为它是一个成员变量和成员方法,所以java可以确定是Circle c的一个实例之前,你的method2()被调用。

希望我能帮上忙。

static方法内部和方法外部创建实例是不同的。

当您在静态方法中访问它们时,变量引用必须是静态的,或者它们必须是该静态方法的局部引用。

案例1

当你在方法外部定义Circle c = new Circle();时,它将成为一个实例成员,并且你不能在静态方法中访问它。

例2:

public static void method2() { 
    Circle c = new Circle();
    System.out.println("What is radius "+ c.getRadius()); 
}

在这种情况下,c是该方法的局部,并且实例成员从未出现在图中。

寓意:不能在静态方法中访问Instance成员

来自文档:

Not all combinations of instance and class variables and methods are allowed:
- Instance methods can access instance variables and instance methods
  directly.
- Instance methods can access class variables and class methods
  directly.
- Class methods can access class variables and class methods directly.
- Class methods cannot access instance variables or instance methods
  directly—they must use an object reference. Also, class methods
  cannot use the this keyword as there is no instance for this to refer to.

基于以上:

    你的原始代码有一个试图访问实例的类方法
  • 在修改后的代码中的第一个示例中,声明变量c 中的静态方法,以便变量是可访问的
  • 在第二个修改后的例子中,方法是一个实例方法,试图访问实例变量,这也是允许的。

在OP中,似乎对静态的含义有些混淆。

静态函数是在没有任何封闭实例的情况下可用的函数。这意味着它可以根据语法Class.function调用。非静态函数需要创建对象的实例
Object instance = using new Object{}
instance.method()

为了实现这一点,静态函数应该是无状态的是一个必要条件。也就是说,唯一可以访问的变量要么是函数的作用域,要么是方法参数,要么是封闭类的静态成员。因此,禁止静态方法试图改变其封闭类的任何非静态成员。

:

public class Demo{
    public static int staticCounter = 0;
    public int instanceCounter = 0;
    public static int getStaticCounter(){
        return staticCounter++;
    }
    public int getInstanceCounter(){
        staticCounter++;
        return instanceCounter++;
    }
}
所以我可以从下面的代码中调用这些函数@
public class widget{
    public static void main(String arg[]){
        System.out.println(demo.getStaticCounter()); // returns zero 
        //Node that I can access the static method before creating any object;
        Demo widget = new Demo();
        System.out.println(widget.getInstanceCounter()); //returns zero
        System.out.println(widget.getInstanceCounter()); //returns one

        System.out.println(widget.getStaticCounter()); // returns 2.
        // note that its generally considered bad practice to call a static method via an instance. Call Demo.getStaticCOunter() instead.
        Demo anotherWidget = new Demo();
        System.out.println(anotherWidget.getInstanceCounter()); //returns zero
        System.out.println(anotherWidget.getInstanceCounter()); //returns one
        //since these get a new copy of the instance variable...
        System.out.println(Demo.getStaticCounter()); // returns 5.
        //but share their static variable.
    }
}

您正在使用实例方法,因此您需要该类的对象来访问它。只有当您有该类的对象时,您才能访问实例方法(如果方法或变量中没有static关键字,则是实例方法或变量)。但是对于静态方法,您不需要创建该类的对象。