公共静态void main()访问非静态变量

14
据说在静态方法中不能使用非静态变量。但是public static void main可以,为什么?

3
静态方法无法访问非静态变量,但是你可以在方法本身中定义局部变量(通过这些局部变量来访问非静态变量)。请用一个例子加以说明。 - Erich Schreiner
6个回答

26
不,它不会。
public class A {
  int a = 2;
  public static void main(String[] args) {
    System.out.println(a); // won't compile!!
  }
}

但是
public class A {
  static int a = 2;
  public static void main(String[] args) {
    System.out.println(a); // this works!
  }
}

如果您实例化A

public class A {
  int a = 2;
  public static void main(String[] args) {
    A myA = new A();
    System.out.println(myA.a); // this works too!
  }
}

此外

public class A {
  public static void main(String[] args) {
    int a = 2;
    System.out.println(a); // this works too!
  }
}

这段代码会正常工作,因为a是一个局部变量,而不是实例变量。方法局部变量在方法执行期间始终可达,无论该方法是否为static


1
公共类 A { public static void main(String[] args) { int a = 2; System.out.println(a); // 这个有效! } } 我的问题是这是如何运作的 - user1526671

10

是的,主方法可以访问非静态变量,但只能通过实际实例间接访问。

例如:

public class Main {
    public static void main(String[] args) {
        Example ex = new Example();
        ex.variable = 5;
    }
}

class Example {
    public int variable;
}

当人们说“非静态变量不能在静态方法中使用”时,他们的意思是同一类的非静态成员无法直接访问(例如在Keppils答案中所示)。

相关问题:


更新:

谈论非静态变量时,隐含地指的是成员变量。 (因为局部变量无法具有静态修饰符。)

在代码中:

public class A {
    public static void main(String[] args) {
        int a = 2;
        System.out.println(a); // this works!
    }
}

你正在声明一个本地变量(通常即使它没有静态修饰符也不被称为非静态)。


公共类A { 公共静态无返回值主函数(String[] args) { int a = 2; System.out.println(a); // 这个可以工作! } } 这不使用任何实例。 - user1526671

3
主方法也无法访问非静态成员。
final public class Demo
{
   private String instanceVariable;
   private static String staticVariable;

   public String instanceMethod()
   {
      return "instance";
   }

   public static String staticMethod()
   {
      return "static";
   }

   public static void main(String[] args)
   {
      System.out.println(staticVariable); // ok
      System.out.println(Demo.staticMethod()); // ok

      System.out.println(new Demo().instanceMethod()); // ok
      System.out.println(new Demo().instanceVariable); // ok

      System.out.println(Demo.instanceMethod()); // wrong
      System.out.println(instanceVariable);         // wrong 
   }
}

这是因为在调用方法或变量时,默认情况下它实际上正在访问this.method()或this.variable。但是在main()方法或任何其他静态方法()中,还没有创建“this”对象。

从这个意义上说,静态方法不是包含它的类的对象实例的一部分。这就是实用类背后的思想。

要在静态上下文中调用任何非静态方法或变量,您需要首先使用构造函数或工厂构造对象,就像在类之外的任何地方一样。


更深入的解释:

基本上,这是Java设计中的一个缺陷,允许静态成员(方法和字段)被引用,好像它们是实例成员一样。这在以下代码中可能会非常令人困惑:

Thread newThread = new Thread(runnable);
newThread.start();
newThread.sleep(1000);

这看起来像是将新的线程休眠,但实际上它会被编译成像这样的代码:

Thread newThread = new Thread(runnable);
newThread.start();
Thread.sleep(1000);

因为sleep是一个只让当前线程休眠的静态方法。

事实上,该变量甚至不再检查是否为非空(我相信它曾经这样做过):

Thread t = null;
t.sleep(1000);

一些集成开发环境可以配置警告或错误,以便对像这样的代码进行提示 - 你不应该这样做,因为它会影响可读性。(这是 C# 修正的缺陷之一...)


那么,如果静态方法和变量不在它们定义的类中,它们会被包含在哪里? - Bbvarghe
Java中静态变量何时被初始化。 - Lion
那么,main方法能够访问instanceMethod和instanceVariable的唯一方式是创建Demo类的对象? - Bbvarghe
如果instanceMethodinstanceVariable分别是实例方法和实例变量,那么它们只能通过将它们解引用为其各自类的对象来从静态方法中访问。 - Lion

3

在这里,您可以看到一张表格清晰地展示了静态和非静态数据成员在静态和非静态方法中的访问情况。static non-static table


0
public class XYZ
{
   int i=0;

   public static void increment()
   {
       i++;   
   }
}

public class M
{
    public static void main(String[] args)
    {
        XYZ o1 = new XYZ();
        XYZ o2 = new XYZ();
        o1.increment(); 
        XYZ.increment(); // system wont be able to know i belongs to which object 
                  // as it increment method (static method) can be called using class name system 
                  // will be confused changes belongs to which object.
    }
}

0

在静态方法中,您可以创建非静态引用,例如:

static void method() {
   A a = new A();
}

public static void main(String[] args) 方法中我们进行同样的操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接