非常常见的初学者错误是当您尝试"静态"使用类属性而不创建该类的实例时.它会留下您提到的错误消息:
您可以将非静态方法设为静态,也可以使该类的实例使用其属性.
为什么?我不是要求解决方案.我很高兴知道它背后的原因是什么.核心原因!
private java.util.ListsomeMethod(){ /* Some Code */ return someList; } public static void main(String[] strArgs){ // The following statement causes the error. You know why.. java.util.List someList = someMethod(); }
Brian Knobla.. 352
你不能打电话给不存在的东西.由于尚未创建对象,因此尚不存在非静态方法.静态方法(根据定义)始终存在.
你不能打电话给不存在的东西.由于尚未创建对象,因此尚不存在非静态方法.静态方法(根据定义)始终存在.
您尝试调用的方法是实例级方法; 你没有实例.
static
方法属于类,非static
方法属于类的实例.
面向对象编程的本质是将逻辑与其操作的数据一起封装.
实例方法是逻辑,实例字段是数据.它们共同构成了一个对象.
public class Foo { private String foo; public Foo(String foo){ this.foo = foo; } public getFoo(){ return this.foo; } public static void main(String[] args){ System.out.println( getFoo() ); } }
运行上述程序的结果可能是什么?
没有对象,就没有实例数据,虽然实例方法作为类定义的一部分存在,但它们需要一个对象实例来为它们提供数据.
理论上,不访问任何实例数据的实例方法可以在静态上下文中工作,但实际上没有任何理由将其作为实例方法.无论如何,这是一个语言设计决定,而不是制定一个额外的规则来禁止它.
我刚刚意识到,我认为人们不应该很早就接触到"静态"的概念.
静态方法应该是例外而不是常态.如果你想学习OOP,尤其是早期.(为什么从规则的例外开始?)这是Java的反教学法,你应该学习的"第一"东西是公共静态无效的主要东西.(很少有真正的Java应用程序有自己的主要方法.)
我认为值得指出的是,通过Java语言的规则,Java编译器会插入相当于"this"的内容.当它注意到您在没有显式实例的情况下访问实例方法或实例字段时.当然,编译器知道它只能从具有"this"变量的实例方法中执行此操作,而静态方法则不会.
这意味着当您使用实例方法时,以下内容是等效的:
instanceMethod(); this.instanceMethod();
这些也是等价的:
... = instanceField; ... = this.instanceField;
编译器正在有效地插入"this".当您不提供特定实例时.
编译器的"神奇帮助"这一点(双关语)会使初学者感到困惑:它意味着实例调用和静态调用有时看起来具有相同的语法,而实际上是不同类型和底层机制的调用.
由于支持多态的虚方法的行为,实例方法调用有时被称为方法调用或调度; 无论您是编写要使用的显式对象实例还是编译器插入"this",都会发生调度行为.
静态方法调用机制更简单,就像非OOP语言中的函数调用一样.
就个人而言,我认为错误消息具有误导性,它可能是"非静态方法无法在未指定显式对象实例的情况下从静态上下文中引用 ".
编译器抱怨的是它不能简单地插入标准"this".就像在实例方法中一样,因为这段代码在静态方法中; 但是,也许作者只是忘了为这个调用提供感兴趣的实例 - 例如,一个可能作为参数提供给静态方法的实例,或者在这个静态方法中创建的实例.
简而言之,您肯定可以在静态方法中调用实例方法,您只需要为调用指定一个显式实例对象.
到目前为止,答案描述了原因,但这里有一些你可能想要考虑的事情:
您可以通过向其构造函数附加方法调用来从可实例化的类中调用方法,
Object instance = new Constuctor().methodCall();
要么
primitive name = new Constuctor().methodCall();
这很有用,您只希望在单个范围内使用一次可实例化类的方法.如果从单个作用域内的可实例化类调用多个方法,则肯定会创建一个可参考的实例.