Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java静态方法可以调用构造函数,但不能引用它?_Java_Constructor_Static_Instance - Fatal编程技术网

为什么Java静态方法可以调用构造函数,但不能引用它?

为什么Java静态方法可以调用构造函数,但不能引用它?,java,constructor,static,instance,Java,Constructor,Static,Instance,我的假设: 静态方法不能调用非静态方法 构造函数是一种无返回类型的方法 给出这个例子 public class Main { public static void main(String[] args) { Main p = new Main(); // constructor call k(); // [implicit] `this` reference } protected Ma

我的假设:

  • 静态方法不能调用非静态方法
  • 构造函数是一种无返回类型的方法
  • 给出这个例子

        public class Main {
            public static void main(String[] args) {
                Main p = new Main();  // constructor call
                k();  // [implicit] `this` reference
            }
    
            protected Main() {
                System.out.print("1234");
            }
    
            protected void k() {
            }
        }
    
    • 此行打印1234:
      Main p=new Main()
    • 此行引发异常:
      k()
    为什么示例代码要做这两件事?它们是否与我的上述假设相冲突?我的假设正确吗

    1-静态方法无法调用非静态方法

    当然可以,但是他们需要一个对象来调用方法

    在静态方法中,没有可用的
    this
    引用,因此
    foo()
    (相当于
    this.foo()
    )是非法的

    2-构造函数是一种没有返回类型的方法

    如果应该的话,我会说构造函数更接近非静态方法(因为构造函数中确实存在
    这个
    引用)

    鉴于这种观点,您应该清楚为什么静态方法可以毫无问题地调用构造函数


    总而言之:

    Main p = new Main();
    
    可以,因为
    newmain()
    不依赖任何现有对象

    k();
    

    不正常,因为它相当于
    this.k()
    ,并且
    this
    在您的(静态)main方法中不可用。

    否。构造函数在这方面不是普通方法。构造函数的全部目的是构造类的一个新实例

    所以它也可以在静态范围内调用。试想一下:如果您需要类的一个现有实例来创建它的一个新实例,您将永远无法实例化它

    一些澄清:

    静态方法不能调用非静态方法

    不完全是。您可以从静态方法内部调用非静态方法,只需将其范围限定到该类的特定对象。即

    p.k();
    
    将在上面的代码示例中完美地工作

    电话

    k();
    
    在实例(非静态)方法中就可以了。这相当于

    this.k();
    
    隐含的
    引用类的当前实例。每当编译器在实例方法中看到像
    k()
    这样的非限定调用时,它将自动使用
    this来限定它的范围。
    。但是,由于静态方法没有绑定到类的任何实例,因此您(和编译器)不能在静态方法中引用此
    。因此,您需要显式地命名类的一个实例,以便在其上调用实例方法

    规则很简单:
    1-静态方法无法调用非静态方法

    那根本不是真的。静态方法可以仅通过“目标”引用调用非静态方法。例如,这在静态方法中很好:

    Integer x = Integer.valueOf(10);
    int y = x.intValue(); // Instance method!
    
    真正的要点是“静态方法中没有
    这个
    引用”

    2-构造函数是一种没有返回类型的方法

    老实说,这不是一个真正有用的模型。从调用方的角度来看,将构造函数看作是一个静态方法,它的返回类型与声明类相同,但无论如何都不是一个完美的模型。


    我建议您将构造函数视为不同类型的成员。接受构造函数和方法之间的差异,而不是试图隐藏它们。

    如果无法从静态方法调用构造函数,那么您永远无法构造任何对象。让人们一直困惑的是
    new main()
    不是一个简单的构造函数调用——它是一元运算符
    new
    的应用,同时指定调用哪个构造函数作为更广泛的分配+初始化过程的一部分。@MarkoTopolnik,JLS reference?您真的需要它吗,因为它很明显?应用
    new
    从堆中分配内存——例如,这不是在构造函数中编写的。它还调用所有实例初始值设定项——另一个对您来说显而易见的事实。在构造器代码中的任何地方都没有写。它还使用突然定义的
    this
    调用构造函数——不是由调用方定义的,而是由隐式代码定义的。构造函数实际上只是一个回调,我之所以这么问是因为我怀疑您在对Java的编译和执行方式做出具体实现的假设。当然,构建一个对象需要运行实例初始值设定项等,但是分配过程,它如何在称为堆的东西上结束,以及这个
    如何突然具体化,我不确定是否在语言规范中定义。(虽然我可能错了。)好的,但是JLS也没有规定
    new X()
    仅仅是一个函数调用——这是要点的核心,由于人们通常以这种方式对其进行可视化,并将其与Java中的其他类型的函数进行错误的比较。您认为如何将构造函数比作作为对象初始化一部分调用的无效返回回调?在我看来,这种程度的间接性是一种逃避人们而导致错误假设的东西。@MarkoTopolnik:这取决于你是从调用者的角度考虑它(在这种情况下,“返回无效”是胡说八道,因为你可以使用结果)还是从实现的角度(在这种情况下它是有意义的)。我更愿意把它看作是它自己的类型,而不是试图对方法进行曲折的类比。如果你考虑到调用者只是在应用
    new
    而没有调用任何函数这一事实,那就不是胡说八道了。事实上,这是我的主要观点——一个人必须尊重新的,而不是浏览它。该运算符的返回值是引用,构造函数仍然可以被视为一个返回回调。我同意类比只能走这么远,但它们仍然有助于