A coworker (who is very new to Java) stopped in today and asked what seemed like a very simple question. Unfortunately, I did an absolutely horrible job of trying to explain
The same reason you can call a method on line 42 that isn't defined until line 78? Java isn't a scripting language, so things don't have to be declared before they are used (this is even true of some scripting languages, actually). Class definitions are considered as a whole at compile time.
You can even instantiate an object of a class in its own constructor:
public class Test {
Test a;
Test() {
a = new Test();
}
public static void main(String[] args) {
System.out.println(new Test());
}
}
This produces... wait for it... a java.lang.StackOverflowError
.
You are defining the class, all its fields and methods etc at compile time. The instance is not created until runtime. So there is no contradiction, the class is fully defined by the time you reach line #1.
As others point out, because the main
method is static
you will reach line #1 without having instantiated an object, but you can do so without issue. I use this pattern all the time for one-class experiments.
A class is loaded into memory by classloader and is initialized if any of the following happens.
1) an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
2) an static method of Class is invoked.
3) an static field of Class is assigned.
4) an static field of class is used which is not a constant variable.
5) if Class is a top level class and an assert statement lexically nested within class is executed.
so by line 1, class is both loaded and initialized and hence there is no problem in instantiating an instance of class in itself.
But if your code is like this,
class Test {
Test test2 = new Test();
public static void main(String[] args) {
Test test1 = new Test();
}
}
the above code will result in stackoverflow exception.
class Test {
public static void main(String[] args) {
Test test = new Test();
}
}
In the above code creating an instance won't call main again.
Remember, main is a static method, not tied to any particular instance.
class Test {
static Test test2 = new Test();
public static void main(String[] args) {
Test test1 = new Test();
}
}
This code will also run fine.
Read more from https://javarevisited.blogspot.in/2012/07/when-class-loading-initialization-java-example.html