tags:

views:

452

answers:

8
class ClassA {
    void h() { }
}

class ClassB extends ClassA{

    public static void main(String[] args){
       ClassA a = new ClassA();
       ClassB b = new ClassB();
  }
}

Yes, everyone think it's such simple and there must and definitely should be only two objects created.

But after I read the "Think in Java,2nd Edition", I think it may contain some more interesting thing here.

In "Think in Java", there is a sentence:" When you create an object of the derived class ,it contains within it a subobject of the base class.This subobject is the same as if you had created an object of the base class by itself."

It is in page 278 for 2nd Edition. You can also see it through this link "http://www.codeguru.com/java/tij/tij0065.shtml" (the section with big title "Initializing the base class")

+3  A: 

3 constructors being called to create 2 objects.

Ariel
Where are 3 constructors being called? How can a constructor be called without creating an object?
Jon Skeet
Doesn't the true thing is there should a subobject with the type of its parent class created when creating one object?
higer
higer: No. There are no subobjects due to inheritance.
ammoQ
+13  A: 

Should be 2. The main function is static so it doesn't need an object.

ClassA a is an object and ClassB b is an object

EDIT: ClassB doesn't consist of two objects because extends is an is-a relationship and not a has-a relationship. (ta mik)

EDIT: There is also the String[] object that is created by the runtime system, and potentially any number of string objects place within that array. I am purposefully ignoring these but acknowledge their possible existence. (ta diveshpremdeep and Adam Goode)

FINAL EDIT: In order to determine how many objects are created (by the program, not the runtime system) you can use the javap program on the commandline like so (if test.java contains your example)

$ javac test.java
$ javap -c ClassB

output:

Compiled from "test.java"
class ClassB extends ClassA{
ClassB();
  Code:
   0:   aload_0
   1:   invokespecial #1; //Method ClassA."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   new #2; //class ClassA
   3:   dup
   4:   invokespecial #1; //Method ClassA."<init>":()V
   7:   astore_1
   8:   new #3; //class ClassB
   11:  dup
   12:  invokespecial #4; //Method "<init>":()V
   15:  astore_2
   16:  return

}

As you can see, there are only two bits of bytecode that are new (which creates objects I assume). One for class ClassA and the other for class ClassB. You can note that the invokespecial command is invoked afterwards to call the constructor, and also how class ClassA's constructor is called from class ClassB's constructor, but no new object is created inside the constructor (it is the default empty constructor).

calling javap -c ClassA shows an equally boring constructor which invokes the constructor for Object.

In summary: It is the new bytecode which creates objects on the heap, not the invokespecial which merely fills in the details of the memory allocated by the new bytecode.

barkmadley
but I think when creating object a,it will create a subobject with the type of Object,because it implicitly extends Object. The same as B.
higer
No "subobjects" are created. ClassB is-a ClassA (but with extra B funkyness) rather has-a ClassA.
mlk
If is as what you say, then by what way can I prove that the subobjects really do not exist or be created?
higer
higer: Theoretically, you could look at the heap, and you would find just 2 objects.
ammoQ
Can you tell me how to look at the heap? Debug in Eclipse?
higer
As mentioned below, don't forget about the args array!
Adam Goode
higer: Can you prove it? (Maybe he is right, but i don't think so)Maybe some internal implementation of the JRE do it this way but from the language point of view there are no subobjects created.
Carlos Muñoz
Jarlac: Yes,thank you! Barkmadley show a good way to make me convinced.
higer
barkmadley: thank you very much! I think I get the answer now.Hope you can accept my great thanks for your time to solve my curiousness .
higer
@higer: about looking at the heap, check my answer below.
Eemeli Kantola
+2  A: 

Two objects are created - an instance of ClassA and an instance of ClassB.

Calling new ClassB() does not call the main() method. The default constructor, which is of the form

public ClassB() {}

will be used. The same goes for ClassA.

Cosmic Flame
+2  A: 

What about the String array being passed to the main method ? That too is an object, ain't it ?

divesh premdeep
This makes things complicated and I don't think the point of this problem is here.
higer
You really think so ? 'Cuz I think the String array would almost always get overlooked while trying to answer this question.Apologies anyways.
divesh premdeep
It's ok. Actually your consideration is correct, while I just want to make clear that are there some subobjects created.
higer
The string array is not _created in the following code_, but somewhere outside. If we understood the question like this, there were actually 98 objects created when I run the program, because I called it with 95 command line parameters.
ammoQ
Yes, you are right.
higer
A: 

The default constructor, calls the super() (parent default constructor) constructor automaticly. So if you create a ClassB object a ClassA object would be created, too.

TiPoK
Nod. But others don't think so and there is not a convincingly way to make me clear about this problem.
higer
+1  A: 

Only

2

Although B extends A when it gets created the constructor in A is executed but at the end only one object out of B is created.

1A + 1B = 2 objects

As for:

"When you create an object of the derived class ,it contains within it a subobject of the base class.This subobject is the same as if you had created an object of the base class by itself."

That means, the following is possible:

 ClassA a = new ClassA();
 a = new ClassB();

That is, you can assign an instance of B to a reference of type A, because:

"...This subobject is the same as if you had created an object of the base class by itself"

That is what the "is-a" relationship is all about. You can say that "every B is-a A" and that's true.

What you can't do though is to invoke a method defined in B which is not defined in A

I hope that helps.

OscarRyz
Thanks for your attention!
higer
A: 

This appears to be one of those questions your professor asks to make you think at an abstract level.

That being said I am willing to bet its 4 objects being created:

1) Class A

2) Class B

3) String[]

4) Since there is no such thing as a string array it is a char array.

Of course that is just a purely theoretical idea

Woot4Moo
+2  A: 

If you mean objects inside the main method block, then 2. This can be verified for example with a Java heap dump and the following code extension:

class ClassA {
    void h() { }
}

class ClassB extends ClassA{
    public static void main(String[] args) throws Exception {
        System.in.read();
        main1(args);
        System.in.read();
    }

    public static void main1(String[] args){
       ClassA a = new ClassA();
       ClassB b = new ClassB();
  }
}

So:

  1. Compile the class and run it. The program execution stops at System.in.read().
  2. Find out the process id.
  3. Run jmap -dump:format=b,file=snapshot1.jmap PROCESS_ID
  4. Hit any key in the console to continue execution.
  5. Run jmap -dump:format=b,file=snapshot2.jmap PROCESS_ID
  6. Hit any key again to finish the program.

After that, you get two Java heap dump snapshots which you can compare.

I got the following values (with Java 1.6.0_15, OSX):

  • snapshot1.jmap: 17584 objects
  • snapshot1.jmap: 17586 objects

The difference is 2, which is also the number of created objects.

Eemeli Kantola