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

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

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

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();         
}

当前回答

如果一个方法不是静态的,这就“告诉”编译器该方法需要访问类中的实例级数据(就像一个非静态字段)。除非创建了类的实例,否则此数据将不可用。因此,如果你试图从静态方法调用该方法,编译器会抛出一个错误。如果实际上该方法没有引用类的任何非静态成员,则将该方法设置为静态。

例如,在Resharper中,只要创建一个不引用类的任何静态成员的非静态方法,就会生成一个警告消息“此方法可以被设置为静态”。

其他回答

到目前为止,答案描述了原因,但还有一件事你可能需要考虑:

你可以通过将方法调用附加到可实例化类的构造函数来调用方法,

Object instance = new Constuctor().methodCall();

or

primitive name = new Constuctor().methodCall();

如果您只希望在单个作用域内使用一次可实例化类的方法,这是非常有用的。如果在一个作用域中从一个可实例化类调用多个方法,一定要创建一个可引用的实例。

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

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

instanceMethod();
this.instanceMethod();

这些也是等价的:

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

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

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

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

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

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


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

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

所以你问的是一个非常核心的原因?

Well, since you are developing in Java, the compiler generates an object code that the Java Virtual Machine can interpret. The JVM anyway is a binary program that run in machine language (probably the JVM’s version specific for your operating system and hardware was previously compiled by another programming language like C in order to get a machine code that can run in your processor). At the end, any code is translated to machine code. So, create an object (an instance of a class) is equivalent to reserve a memory space (memory registers that will be processor registers when the CPU scheduler of the operating system put your program at the top of the queue in order to execute it) to have a data storage place that can be able to read and write data. If you don’t have an instance of a class (which happens on a static context), then you don’t have that memory space to read or write the data. In fact, like other people had said, the data don’t exist (because from the begin you never had written neither had reserved the memory space to store it).

对不起我的英语!我是拉丁!

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

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

您正在尝试调用的方法是实例级方法;您没有实例。

静态方法属于类,非静态方法属于类的实例。