F
Fernando
In resume, I have a factory class that creates/instantiates a family
of classes, like in this example:
public class Test{
public static void main(String args[]){
TestInterface t = Factory.getInstance(0);
t.f();
}
}
class Factory{
public static TestInterface getInstance(int type){
System.out.println("Executed Factory.getInstance()");
switch(type){
case 0: return new TestInterfaceImpl0();
case 1: return new TestInterfaceImpl1();
default: return new TestInterfaceImpl2();
}
}
}
abstract class TestInterface{
public abstract void f();
}
class TestInterfaceImpl0 extends TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl0.f()"); }
}
class TestInterfaceImpl1 extends TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl1.f()"); }
}
class TestInterfaceImpl2 extends TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl2.f()"); }
}
When I run Test class using -verbose:class option I got this output:
[Loaded Test]
[Loaded Factory]
[Loaded TestInterface]
[Loaded TestInterfaceImpl0]
[Loaded TestInterfaceImpl1]
[Loaded TestInterfaceImpl2]
Executed Factory.getInstance()
Executed TestInterfaceImpl0.f()
So, what we see here is that JVM loads ALL classes referenced from
Factory.getInstance() (TestInterfaceImpl0, TestInterfaceImpl1 and
TestInterfaceImpl2) before it is executed.
Now, my question. If I change the abstract class TestInterface into an
interface, the loading order is completely different. See:
public class Test{
public static void main(String args[]){
TestInterface t = Factory.getInstance(0);
t.f();
}
}
class Factory{
public static TestInterface getInstance(int type){
System.out.println("Executed Factory.getInstance()");
switch(type){
case 0: return new TestInterfaceImpl0();
case 1: return new TestInterfaceImpl1();
default: return new TestInterfaceImpl2();
}
}
}
interface TestInterface{
public void f();
}
class TestInterfaceImpl0 implements TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl0.f()"); }
}
class TestInterfaceImpl1 implements TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl1.f()"); }
}
class TestInterfaceImpl2 implements TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl2.f()"); }
}
When I run Test class using -verbose:class option I got this output:
[Loaded Test]
[Loaded Factory]
[Loaded TestInterface]
Executed Factory.getInstance()
[Loaded TestInterfaceImpl0]
Executed TestInterfaceImpl0.f()
This time, ONLY TestInterfaceImpl0 is loaded and its loading is
postponed until it is needed (Factory.getInstance() before the
loading).
Does anyone now why this happens?
Thanks a lot.
Regards,
Fernando.
of classes, like in this example:
public class Test{
public static void main(String args[]){
TestInterface t = Factory.getInstance(0);
t.f();
}
}
class Factory{
public static TestInterface getInstance(int type){
System.out.println("Executed Factory.getInstance()");
switch(type){
case 0: return new TestInterfaceImpl0();
case 1: return new TestInterfaceImpl1();
default: return new TestInterfaceImpl2();
}
}
}
abstract class TestInterface{
public abstract void f();
}
class TestInterfaceImpl0 extends TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl0.f()"); }
}
class TestInterfaceImpl1 extends TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl1.f()"); }
}
class TestInterfaceImpl2 extends TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl2.f()"); }
}
When I run Test class using -verbose:class option I got this output:
[Loaded Test]
[Loaded Factory]
[Loaded TestInterface]
[Loaded TestInterfaceImpl0]
[Loaded TestInterfaceImpl1]
[Loaded TestInterfaceImpl2]
Executed Factory.getInstance()
Executed TestInterfaceImpl0.f()
So, what we see here is that JVM loads ALL classes referenced from
Factory.getInstance() (TestInterfaceImpl0, TestInterfaceImpl1 and
TestInterfaceImpl2) before it is executed.
Now, my question. If I change the abstract class TestInterface into an
interface, the loading order is completely different. See:
public class Test{
public static void main(String args[]){
TestInterface t = Factory.getInstance(0);
t.f();
}
}
class Factory{
public static TestInterface getInstance(int type){
System.out.println("Executed Factory.getInstance()");
switch(type){
case 0: return new TestInterfaceImpl0();
case 1: return new TestInterfaceImpl1();
default: return new TestInterfaceImpl2();
}
}
}
interface TestInterface{
public void f();
}
class TestInterfaceImpl0 implements TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl0.f()"); }
}
class TestInterfaceImpl1 implements TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl1.f()"); }
}
class TestInterfaceImpl2 implements TestInterface{
public void f(){ System.out.println("Executed
TestInterfaceImpl2.f()"); }
}
When I run Test class using -verbose:class option I got this output:
[Loaded Test]
[Loaded Factory]
[Loaded TestInterface]
Executed Factory.getInstance()
[Loaded TestInterfaceImpl0]
Executed TestInterfaceImpl0.f()
This time, ONLY TestInterfaceImpl0 is loaded and its loading is
postponed until it is needed (Factory.getInstance() before the
loading).
Does anyone now why this happens?
Thanks a lot.
Regards,
Fernando.