关于Java中类成员的问题

关于Java中类成员的问题,java,oop,compiler-construction,constructor,Java,Oop,Compiler Construction,Constructor,如果我有一个类SOmeClass和一个方法someMethod,在下面的代码中,编译器如何读取类成员someConstant Class SomeClass{ private int someConstant = someMethod(3); //3 is arbitrary private int anotherConstant; SomeClass(){ //constructor

如果我有一个类SOmeClass和一个方法someMethod,在下面的代码中,编译器如何读取类成员someConstant

Class SomeClass{
            private int someConstant = someMethod(3); //3 is arbitrary

            private int anotherConstant;
            SomeClass(){
                 //constructor
                 anotherConstant = someConstant;
                     }

            public int someMethod(int an_int_value){
                 //something
                    return new_int;
                      }

这个问题是关于我对编译器如何工作的困惑。以及机器如何读取代码。常量someConstant在类实例化之前无法启动,因为编译器需要知道方法someMethod的作用。但构造函数无法完成,因为另一个常量也需要具有此未知值。在我(一个没有计算机科学经验的人)看来,这是一个两难的局面。这个问题不仅限于Java。这只是我最熟悉的语言。

Java中的对象实例化是一个多步骤的过程。首先,类中的每个字段都初始化为其默认值(0、false或null,视情况而定)。接下来,每个带有初始值设定项的字段依次初始化为该值。如果这意味着调用任何方法,那么调用这些方法时,字段要么保留其默认值(如果尚未触及它们),要么保留其已初始化的值。最后,调用构造函数


请注意,这意味着对象的内存是在构造函数运行之前分配的。为了使这种方法发挥作用,这是必要的。

我不是Java虚拟机方面的专家,我仍将尝试回答您的问题:

  • 您的问题实际上与编译器无关-编译器只将可读的Java代码转换为二进制指令。在运行时会出现未初始化变量的问题,除非编译器足够“聪明”在代码中找到循环依赖项

  • 没有一个值是常量-它们必须声明为
    final
    ,如果以这种方式声明,您将无法设置另一个
    常量。它们都是变量

  • 首先,您的类将被加载到内存中。因此,
    SomeClass
    的基本内存布局以及
    someMethod()
    的功能都是已知的。如果声明了静态变量,它们现在也会被初始化,但是不能调用像
    someMethod
    这样的实例方法

  • 当实例化类型为
    SomeClass
    的对象时,将首先设置所有成员变量,因此
    someConstant
    将不再是未知的。由于
    someMethod
    的功能也是已知的,因此这应该不是问题。如果您在
    someMethod
    中的某个点引用未声明的变量,将抛出
    NullPointerException

  • 最后,调用构造函数。在这一点上,所有成员变量都是可用的,因此它将顺利运行。同样-如果存在任何未声明的变量,将抛出
    NullPointerException
    。但是,在您的示例中,不应该有


  • 您似乎混淆了编译器和运行时。
    someMethod()
    的作用是在编译时确定的,并存储在输出的.class文件中。运行时读入这些.class文件并从中生成类定义。因此,在您尝试实例化
    SomeClass
    之前,它完全了解someMethod()的功能。在类的方法具有定义之前,构造函数不需要完成运行

    java所做的是按照声明的顺序运行所有初始值设定项,然后启动实际构造函数中的内容。考虑:

    private Integer foo = getFoo();
    private Integer bar = Integer.valueOf(4);
    private Integer getFoo() {return bar;}
    
    当我们完成时,foo将为null,因为它是首先声明的,当我们分配它时,bar仍然为null

    private Integer bar = Integer.valueOf(4);
    private Integer foo = getFoo();
    private Integer getFoo() {return bar;}
    

    这样,当施工完成时,foo将为4!无论哪种方式,运行时都可以在构造函数完成之前查找getFoo()方法的定义,因为编译器将它的定义放在类文件中。

    从构造函数中调用方法也存在同样的问题。我们几乎同时发布了。。你的回答是对的,先生!我的想法是:根据我的理解,在创建类的实例时,JVM将首先创建一个空对象,然后创建实例成员,然后调用构造函数。所以,这里没有问题。执行步骤:1。创建一个空的对象容器。2.实例化实例成员变量。(初始)3。运行构造函数。