Java 背后的原因是什么;无法从静态上下文引用非静态方法";?

Java 背后的原因是什么;无法从静态上下文引用非静态方法";?,java,static,Java,Static,初学者最常见的错误是,当您试图“静态”使用一个类属性而不创建该类的实例时。它会给您留下所提到的错误消息: 您可以使非静态方法成为静态的,也可以使该类的实例使用其属性 为什么?我不是在寻求解决办法。我很想知道背后的原因是什么。最核心的原因 private java.util.List<String> someMethod(){ /* Some Code */ return someList; } public static void main(

初学者最常见的错误是,当您试图“静态”使用一个类属性而不创建该类的实例时。它会给您留下所提到的错误消息:

您可以使非静态方法成为静态的,也可以使该类的实例使用其属性

为什么?我不是在寻求解决办法。我很想知道背后的原因是什么。最核心的原因

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

public static void main(String[] strArgs){          
     // The following statement causes the error. You know why..
    java.util.List<String> someList = someMethod();         
}
private java.util.List someMethod(){
/*一些代码*/
返回一些列表;
}
公共静态void main(字符串[]strArgs){
//以下语句导致错误。您知道原因。。
java.util.List someList=someMethod();
}

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


static
方法属于类,非
static
方法属于类的实例。

您不能调用不存在的东西。由于您尚未创建对象,因此非静态方法还不存在。静态方法(根据定义)总是存在的。

静态方法将动作与对象类型关联,而非静态方法将动作与对象类型的实例关联。通常,它是一种方法,可以执行与实例相关的操作

例:


Car类可能有一个wash方法,该方法指示清洗特定的汽车,而静态方法将应用于Car类型。

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


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

到目前为止的答案描述了原因,但您可能还需要考虑以下事项:

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

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


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

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


静态方法可能是例外,而不是常规方法。如果你想学习OOP,尤其是在早期。(为什么要从规则的一个例外开始?)这与Java的教学法背道而驰,您应该学习的“第一件事”是最主要的事情。(很少有真正的Java应用程序有自己的主方法。)

编译器实际上向非静态方法添加了一个参数。它添加了一个
指针/引用。这也是为什么静态方法不能使用此
,因为没有对象。

面向对象编程的本质是将逻辑及其操作的数据封装在一起

实例方法是逻辑,实例字段是数据。它们一起构成一个物体

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() );
    }
}
运行上述程序的结果可能是什么

没有对象,就没有实例数据,虽然实例方法作为类定义的一部分存在,但它们需要一个对象实例为它们提供数据


从理论上讲,不访问任何实例数据的实例方法可以在静态上下文中工作,但实际上没有任何理由将其作为实例方法。无论如何允许它,而不是制定额外的规则来禁止它,这是一种语言设计决策。

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

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

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() );
    }
}
这意味着当您使用实例方法时,以下内容是等效的:

instanceMethod();
this.instanceMethod();
... = instanceField;
... = this.instanceField;
这些也相当于:

instanceMethod();
this.instanceMethod();
... = instanceField;
... = this.instanceField;
当您不提供特定实例时,编译器将有效地插入“this.”

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

实例方法调用有时被称为方法调用或分派,因为支持多态性的虚拟方法的行为;无论是编写要使用的显式对象实例还是编译器插入了“this”,都会发生分派行为

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

就个人而言,我认为错误消息是误导性的,它可能会读到“如果不指定显式对象实例,就不能从静态上下文引用非静态方法”


编译器抱怨的是,它不能像在实例方法中那样简单地插入标准“this”,因为这段代码在静态方法中;然而,也许作者只是忘记了提供一个有趣的例子