Question about class members in Java
If I have a class SOmeClass, with a method someMethod, in the following code how does the compiler read the class member 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;
}
This question is about my confusion of how compilers work. ANd how the machine reads code. The constant someConstant cannot be initiated until the class is instantiate, because the compiler needs to know what the method someMethod does. But the contructor can't be completed because anotherCOnstant needs to have this unknown value too. It seems to me (someone with no experience of computer science) that this is a catch-22 situation. This question is not limited to Java. It's just my most familiar language.
Object instantiation in Java is a multistep process. First, every field in the class is initialized to its default value (0, false, or null as appropriate). Next, each field with an initializer is, in order, initialized to this value. If this means calling any methods, then those methods are invoked with the fields either holding their default (if they haven't been touched yet) or the value they've been initialized to. Finally, the constructor is invoked.
Notice that this means that the memory for the object is allocated before the constructor runs. This is necessary in order for this approach to work.
You seem to be confusing the compiler with the run time. What the someMethod()
does is determined at compile time and stored in the .class file that is output. The run time reads in these .class files and builds Class definitions from them. So it has a complete knowledge of what someMethod() does before you ever try to instantiate a SomeClass
. There is no restriction that the constructor needs to have finished running before methods of the class have a definition.
What java does is run all of the initializers in the order they're declared, then start what's in the actual constructor. Consider:
private Integer foo = getFoo();
private Integer bar = Integer.valueOf(4);
private Integer getFoo() {return bar;}
foo will be null when we're done, because it was declared first and bar was still null when we assigned it.
private Integer bar = Integer.valueOf(4);
private Integer foo = getFoo();
private Integer getFoo() {return bar;}
This way foo will be 4 when construction is done! Either way, the runtime can look up the definition of the getFoo() method before the constructor is done, because the compiler put a definition of it in the class file.
Not being an expert on the Java VM, I'll still try to answer your question:
Your problem is actually not one that concerns the compiler - the compiler only turns your readable Java code into binary instructions. The problem of having uninitialized variables would occur at runtime, unless the compiler was "smart" enough to find circular dependencies in your code.
None of your values are constants - they would have to be declared
final
, and you would not be able to setanotherConstant
like that if you had it declared that way. They are both variables.At first, your class will be loaded into memory. So the basic memory layout of
SomeClass
will be known, and so will the functionality ofsomeMethod()
. If you had static variables declared, they would also be initialized now, but you couldn't call an instance method likesomeMethod
to do so.When you instantiate an object of type
SomeClass
, all the member variables will be set first, sosomeConstant
will no longer be unknown. Since the functionality ofsomeMethod
is also known, this should not be a problem. Were you referring to an undeclared variable at some point insomeMethod
, aNullPointerException
would be thrown.Finally, the constructor is called. At this point, all the member variables are available, so it all will run smoothly. Again - were there any undeclared variables, a
NullPointerException
would be thrown. In your example, there should not be any, though.
精彩评论