Basic question on objects and references to objects

Suppose you have a class called Car. When you instantiate an object of type Car, the code looks something like this: Car c; c = new Car(); or equivalently, Car c = new car(); I understands that c is a reference variable that points to the object that you just created. But if c is simply a pointer to the actual object, why does it have to be explicitly assigned a type? I mean, c is just a pointer - it isn't actually an object of type Car. The contents of of c is just an address that points to the actual object. The object itself is where the fields and methods are stored. So why must c be declared as type Car? Why must it be declared at all? I mean, if you instantiate c as above, you can tell that it points to an object of type Car. If you must declare c, why is it not declared as an object of a class such as Reference, which is actually what it is? Still trying to "get it".Thanks for any insight anyone can provide.

Hi Dario, Well we have to declare the type to make compiler happy. Consider we have two types of objects, Car Truck Now if we follow the convention you suggest (where we have a type called Reference) then, Reference c = new Car(); Reference t = new Truck(); Now, consider in Car object there is a method isSportsCar(); in Truck object there is a method called isHeavyDutyTruck(); so if we write following statement in there, c.isHeavyDutyTruck() then??? How compiler makes sure that it there is not such method in Car object?? (By looking at new Car() statement??? which is a runtime decision..) similarly how compiler will know t.isSportsCar() is not a valid method call?? This become much simpler to see when we have inheritance and whole subclass/superclass things around us... See there are two phases of a program, 1. Compilation 2. Run time The problems will occur at 1st phase if we don't have such explicit convention of "declaration of type". The RTT (Runtime Type Identification) works at "RUNTIME" not at compile time in any language (C++/Java)...so looking at "new Car()" and determining things for compile time is not feasible... If we could run the program directly w/o compilation then it would work though Hope it helps.. Regards Maulin

Dario Romani

Greenhorn

Posts: 13

posted 14 years ago

Maulin, thank you for your reply. Your explanation is very helpful, but there are still some "loose ends" in my mind, likely doe to my inexperience with Java.

so if we write following statement in there, c.isHeavyDutyTruck() then??? How compiler makes sure that it there is not such method in Car object?? (By looking at new Car() statement??? which is a runtime decision..)

But even before runtime, should the compiler not be able to figure out that the c points to an object of type Car, simply based on the declaration where it is instantiated. After all, the statement explicitly links the reference variable c to a new object of type Car. Surely the compiler parses this statement??

Maulin Vasavada

Ranch Hand

Posts: 1873

posted 14 years ago

Hi Dario But even before runtime, should the compiler not be able to figure out that the c points to an object of type Car, simply based on the declaration where it is instantiated.

Thats the exact problem compiler faces. Consider a super/sub classes as, class Parent { } class Child1 extends Parent { void method1() {} } class Child2 extends Parent { void method2() {} } class Test { public static void main(String[] args) { Parent p1 = new Child1(); p1.method1(); // line-1 p1 = new Child2(); // line-2 p1.method2(); // line-3 p1.method1(); // line-4 } } The above code won't compile in java but assuming it compiled, On line-1 if the compiler applied the logic you suggest then it would identify that "Oh, this is Child1 object and there is method1() in there" so its valid...Now, on line-2 we reassign p1 to Child2() object so on line-3 is now valid as there is method2() in Child2 but line-4 becomes invalid, right? What should compile do here?? Should it warn user or what? You might be wondering why I declare Parent's object instead of just Child1/Child2 but this is the essentially case when we are having Interfaces and we want to hide the implementing class names from the client's. We do, interface I { public void doThings(); } Class A implements I { public void doThings() {} } Class B implements I { public void doThings() {} } Class Test { psvm(String[] s) { // this isn't valid in java but I have used a short cut for main I i1 = Class.forName(s[0]); i1.doThings(); } } where s[0] can be "dynamically" assigned when we run the program. Here, Class.forName() loads the class specified by s[0] name and then calls method doThings() on it but it doesn't have to know whether the class is A or B...so this kind of "hiding" and declaring "Parent's object" is necessary sometimes... I guess I'm not able to explain this but if you ever tried to write your own compiler you would immediately know "why the hack we have to declare things"... Regards Maulin

Maulin Vasavada

Ranch Hand

Posts: 1873

posted 14 years ago

sorry, I i1 = Class.forName(s[0]); is incorrect, it should be, I i1 = (I)Class.forName(s[0]).newInstance();

In addition to what Maulin said, I would add these two points. First: Java enforces stronger type checking than many other languages, such as C or C++. This helps prevent bugs by making sure that a reference refers only to an object with which it is compatible (which is an object of the reference's class or subclass). This is a fundamental and intentional aspect of the language that was decided when Java was invented. Thus, loosely speaking, the strong type checking isn't as much for the compiler's benefit as it is for yours. Second: Java **does** have a generic reference type: its called Object. A reference of type Object can refer to any other type of object because Object is a superclass of all other objects. The only restriction, and its an important restriction, is that the only actions that you can perform through an Object reference are those defined by Object. For example, you can call the methods wait() and notify() on any object because they are defined by Object. If the object being referred to contains a method of its own, such as one named myMeth(), it cannot be called through the Object reference. Thus, even though Object can refer to any type of object, you can only access those parts of the object that are inherited from Object.

For my latest books on Java, including Introducing JavaFX 8 Programming, see HerbSchildt.com

Just to be really picky ... at the beginning you showed examples like Car c = new Car(); This is perfectly good. But it's not the only choice you have. The type of the variable can be Car or any object "up" the inheritance tree. Since all classes extend Object it's always safe to say: Object c = new Car(); But it would not be very useful, because if you wanted to run methods or look at variables defined by Car, the compiler would not let you. The compiler would reason "you told me this variable is an Object and that's all I know about it." So c.getNumberOfDoors() would fail. There might be other useful classes in the inheritance tree. Suppose Car extends a class called Vehicle: Vehicle c = new Car(); Now the compiler lets you reference the methods and variables on Vehicle, so c.getMileage() might still work. Hope that's making sense. Next: Interfaces!

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi

Dario Romani

Greenhorn

Posts: 13

posted 14 years ago

Thank you everyone. It's still a bit fuzzy, but every little tidbit of knowledge and different perspective is nudging me in the right direction. I'm still trying to establish that fudamental framework that everything will (hopefully) start fitting into! Regards to all, Dario R.