初学者最常犯的错误是试图“静态”地使用类属性而不创建该类的实例。它会给你留下上面提到的错误信息:

您可以将非静态方法设置为静态,也可以创建该类的实例来使用它的属性。

背后的原因是什么?我关心的不是解决方法,而是原因。

private java.util.List<String> someMethod(){
    /* Some Code */
    return someList;            
}

public static void main(String[] strArgs){          
     // The following statement causes the error. 
    java.util.List<String> someList = someMethod();         
}

当前回答

非静态方法依赖于对象。一旦对象被创建,程序就会识别它。

静态方法甚至可以在创建对象之前调用。静态方法非常适合于执行不依赖于您计划使用的实际对象的比较或操作。

其他回答

我刚刚意识到,我认为人们不应该过早地接触“静态”的概念。

静态方法应该是例外,而不是规范。尤其是在你想学习OOP的时候。(为什么要从规则的例外开始呢?)这与Java的教学方法截然相反,你应该学习的“第一件”事情是公共静态空的主要内容。(很少有真正的Java应用程序有自己的主方法。)

我认为值得指出的是,根据Java语言的规则,当Java编译器注意到您在没有显式实例的情况下访问实例方法或实例字段时,它会插入等价的“this.”。当然,编译器知道它只能在实例方法中执行此操作,该实例方法有一个“this”变量,而静态方法没有。

这意味着当你在一个实例方法中,以下是等价的:

instanceMethod();
this.instanceMethod();

这些也是等价的:

... = instanceField;
... = this.instanceField;

当您没有提供特定实例时,编译器会有效地插入“this.”。

编译器的这种“神奇帮助”(双关语)可能会让新手感到困惑:这意味着实例调用和静态调用有时看起来具有相同的语法,而实际上是不同类型和底层机制的调用。

实例方法调用有时被称为方法调用或分派,因为虚拟方法的行为支持多态;不管你是写了一个显式的对象实例来使用,还是编译器插入了一个"this.",分派行为都会发生。

静态方法调用机制更简单,就像非oop语言中的函数调用一样。

就我个人而言,我认为错误消息是误导性的,它可以读为“在没有指定显式对象实例的情况下,不能从静态上下文中引用非静态方法”。


编译器抱怨的是它不能像在实例方法中那样简单地插入标准的"this.",因为这段代码是在静态方法中;然而,可能作者只是忘记为这个调用提供感兴趣的实例——例如,一个实例可能作为参数提供给静态方法,或者在这个静态方法中创建。

简而言之,您当然可以从静态方法中调用实例方法,您只需要为调用指定一个显式的实例对象。

你不能给不存在的东西打电话。因为还没有创建对象,所以非静态方法还不存在。静态方法(根据定义)总是存在的。

这背后的简单原因是父类的静态数据成员 可以访问(仅当它们未被覆盖时),但例如(非静态) 数据成员或方法需要它们的引用,因此它们只能是 通过对象调用。

非静态方法依赖于对象。一旦对象被创建,程序就会识别它。

静态方法甚至可以在创建对象之前调用。静态方法非常适合于执行不依赖于您计划使用的实际对象的比较或操作。