据说在静态方法中不能使用非静态变量。但是public static void main可以,为什么?
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
。
是的,主方法可以访问非静态变量,但只能通过实际实例间接访问。
例如:
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!
}
}
你正在声明一个本地变量(通常即使它没有静态修饰符也不被称为非静态)。
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# 修正的缺陷之一...)
instanceMethod
和instanceVariable
分别是实例方法和实例变量,那么它们只能通过将它们解引用为其各自类的对象来从静态方法中访问。 - Lionpublic 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.
}
}
在静态方法中,您可以创建非静态引用,例如:
static void method() {
A a = new A();
}
在 public static void main(String[] args)
方法中我们进行同样的操作。