Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Doubt about Koala question in Mock Exam #2 (Java OCA 8 Programmer I Study Guide, Sybex)

 
Julie P Chen
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, the answer to this question was B, and I chose F because I thought it would throw a "ClassCastException" on Line 9. The explanation is particular confusing when it says "... Line 9 compiles correctly because they are related types..." I assume "they" are referring to "CanClimb" and "HasClaws". But the thing is that they are not related? HasClaws did not extends from CanClimb or vice versa.
Can someone clarify?



A. true15
B. 15true
C. The code will not compile Line 7
D. The code will not compile Line 8
E. The code will not compile Line 9
F. The code compiles but throws an exception at runtime.
 
Claudiu Stroe
Greenhorn
Posts: 29
5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This was a tricky question for me too. In the beginning you are thinking that HasClaws is not related to CanClimb, but as you cand see



The references koala, canClimb and hasClaws are polymorphichally pointing to the same object of new Koala(), so they are correct and no "ClassCastException" will be thrown.

Remember that interfaces are not objects so, they cannot be initialized
 
Ramya Subraamanian
Ranch Hand
Posts: 178
17
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
CanClimb and HasClaws are not related.But Koala implements both these interfaces.
In line1 since Object is the super class of all classes. This is fine.
In line2 you are casting the reference variable to a Interface CanClimb.and you are just assigning that to a CanClimb reference and it compiles. because Koala implements CanClimb it doesnt throw a ClassCastException.
In line3 you are casting the reference variable to a Interface HasClaws.and you are just assigning that to a HasClaws reference, it compiles. because Koala implements HasClaws it doesnt throw a ClassCastException.
Now canClimb has access to method maxHeight of Koala and prints 15. And Similarly hasClaws has access to boolean isSharp() and prints true.
By casting you are not changing the object itself, you are just labelling it differently.there is one Koala Object created with the new operator. It is labelled to different types in 1ine2 and line3.

Like in line4 and line5, you can cast the reference variable to a Interface, it compiles(provided the class is not final and Interfaces are not final). But it will throw a ClassCastException, if they are not related or compatible.

 
Julie P Chen
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for the explanations thus far, but there is still some confusion.

Please clarify some more of any misconception in the paragraphs below.

We know that we can assign a super-class (or interface it implements from) reference type to an object, without explicitly casting, as in Line 1, because all objects are sub-class of java.lang.Object.
So in Line 1, "koala" has reference type of an java.lang.Object, and NOT Koala, even though it is referencing to an Koala object.
So to Java, "koala" is referencing an java.lang.Object object, which compiles because Koala object is also an instance of java.lang.Object.
This is why the reference type determines which methods can be accessed - a super-class reference can not access the methods in the sub-class object.

We know that we can assign a sub-class reference type to an object, with an explicit cast, as in Line 2, because java.lang.Object is the super-class of all objects, including CanClimb.
So Line 2, "canClimb" has a CanClimb reference type, and to Java, it is referencing a CanClimb object, which compiles, because this newly created Koala object is also an instance of CanClimb.

The confusion comes from Line 3 because "canClimb" is a CanClimb reference type, even though we know it is still referencing a Koala object.
So for "canClimb" to be cast to HasClaws reference type, it would only make sense that HasClaws and CanClimb interfaces would have to be related as it is in the Mock Exam Explanation - HasClaws implements CanClimb.

Thus, this still seems like an error in the Mock Exam to me. Or, Line 3 could be a Compiler Error for casting un-related types, if it does not throw an ClassCastException at runtime.

Please clarify some more or point out the misconception. Thanks.



 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Julie P Chen wrote:Can someone clarify?

First of all, this topic has an explanation about exactly the same code snippet. Definitely worth reading! It will probably clear all your doubts/confusion.

Secondly, casting and instanceof is probably one of the more popular topics in this forum. So using the search function you'll probably find a bunch of (very) good topics on this exam objective. These topics contain all valuable information (with code snippets to illustrate rules and possible pitfalls) about casting:
  • Why will this throw Class Cast Exception?
  • Casting
  • Not sure why my answer on overloading was incorrect
  • Some doubts about casting
  • instanceof operator with an interface versus class


  • Julie P Chen wrote:The explanation is particular confusing when it says "... Line 9 compiles correctly because they are related types..." I assume "they" are referring to "CanClimb" and "HasClaws". But the thing is that they are not related? HasClaws did not extends from CanClimb or vice versa.

    Finally, I agree with you: the given explanation is very confusing and it even contains an incorrect statement. Let's have a look at a few statements from the explanation and I'll try to suggest a few improvements (which hopefully will clear your doubts/confusion).

    Practice Exam 2, Explanation wrote:Line 7 compiles correctly since all objects can be implicitly cast to java.lang.Object, so option C is incorrect.

    Each class extends (directly or indirectly) from java.lang.Object, so Koala IS-A java.lang.Object and therefore you can assign a Koala instance/object to a java.lang.Object reference variable (without needing an explicit cast).

    Practice Exam 2, Explanation wrote:Line 8 compiles without issue since CanClimb is a subclass of Object, so option D is incorrect.

    I agree that option D is incorrect, but not with the given explanation. In fact, the given explanation is incorrect! An interface can never be a subclass of a class, an interface can only extend from one (or more) other interfaces not from a class. If that statement would have been true, you could write something likeBut that gives you a big, fat compiler error! The one and only reason why line8 compiles successfully: the compiler knows that reference variable koala is of type Object. Because class Object is not final, you can cast a reference variable to any interface without a compiler error (you might get a runtime ClassCastException if the interface is incompatible). If class Object would have been final, you'll get a compiler error on line8.

    Practice Exam 2, Explanation wrote:Line 9 also compiles correctly since they are related types, so option E is incorrect.

    I agree with you on this one. That's a pretty confusing explanation, because interfaces CanClimb and HasClaws are completely unrelated types. The only way those interfaces could be related types, is if one of them is the superinterface of the other one. The one and only reason why line9 compiles successfully: the compiler knows that reference variable canClimb is of type CanClimb. Because interface CanClimb is an interface (and therefore not final), you can cast a reference variable to any interface without a compiler error (you might get a runtime ClassCastException if the interface is incompatible).

    Practice Exam 2, Explanation wrote:At runtime, all of the casts succeed since Koala implements both CanClimb and HasClaws, so option F is incorrect. The code compiles and runs without issue, with 15true as the output.

    I think this statement is pretty straightforward and crystal-clear. Because Koala implements both CanClimb and HasClaws, Koala IS-A CanClimb and Koala IS-A HasClaws. Therefore both casts will not throw a ClassCastException at runtime.

    Hope it helps!
    Kind regards,
    Roel

    PS. Always use code tags when posting code to the forums. Unformatted or unindented code is extremely hard to read and many people that might be able to help you will just move along to posts that are easier to read. Please click this link ⇒ UseCodeTags ⇐ for more information. Properly indented and formatted code greatly increases the probability that your question will get quicker, better answers. I've gone ahead and added the code tags for you. See how much easier the code is to read? If you want to see a few usage examples (and which options you can use), have a look at the Using Code Tags section of the Ranch Guide.
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ramya Subraamanian wrote:Like in line4 and line5, you can cast the reference variable to a Interface, it compiles(provided the class is not final and Interfaces are not final). But it will throw a ClassCastException, if they are not related or compatible.

    First of all, interfaces can never be final. Never! If you try to add the final modifier to an interface, you'll get a compiler error

    Secondly, why do you add the instanceof operator to both statements on line4 and line5? It is redundant code, which will be never executed as the cast will throw a ClassCastException at runtime. But for a greenhorn who is still learning, it could be (very) confusing and he/she might think that it's the instanceof operator which causes the ClassCastException at runtime. (That's of course impossible, because the instanceof operator returns only true or false; or you might get a compiler error if you use incompatible types). So to avoid that kind of confusion, it's much better to use these statements to illustrate this behaviorOr you could use these statements tooBoth set of statements have the same outcome.

    Hope it helps!
    Kind regards,
    Roel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Julie P Chen wrote:We know that we can assign a sub-class reference type to an object, with an explicit cast, as in Line 2, because java.lang.Object is the super-class of all objects, including CanClimb.
    So Line 2, "canClimb" has a CanClimb reference type, and to Java, it is referencing a CanClimb object, which compiles, because this newly created Koala object is also an instance of CanClimb.

    You are incorrect! Firstly, java.lang.Object is the superclass of all classes, but not of interfaces. Secondly here is one very, very, very important rule you should remember: the compiler doesn't execute any code at all! So the compiler doesn't know (and doesn't care) the type of the object to which the reference variable koala is referring to. The only thing the compiler knows is the type of the reference variable koala (which is java.lang.Object). I have already explained the reason why this line compiles in a previous post, but it's waaaaay to important so I'll just repeat it The one and only reason why line2 compiles successfully: the compiler knows that reference variable koala is of type Object. Because class Object is not final, you can cast a reference variable to any interface without a compiler error.

    Julie P Chen wrote:The confusion comes from Line 3 because "canClimb" is a CanClimb reference type, even though we know it is still referencing a Koala object.
    So for "canClimb" to be cast to HasClaws reference type, it would only make sense that HasClaws and CanClimb interfaces would have to be related as it is in the Mock Exam Explanation - HasClaws implements CanClimb.

    You are correct about the fact that the reference variable canClimb is referring to the Koala object (so there are now two reference variables referring to the same Koala object: koala and canClimb). But you are incorrect about the fact that interfaces HasClaws and CanClimb must be related in order to line3 to compile successfully. Again I have explained the reason why this line compiles in a previous post, but it's waaaaay to important so I'll just repeat it The one and only reason why line3 compiles successfully: the compiler knows that reference variable canClimb is of type CanClimb. Because interface CanClimb is an interface (and therefore not final), you can cast a reference variable to any interface without a compiler error.

    Julie P Chen wrote:Thus, this still seems like an error in the Mock Exam to me. Or, Line 3 could be a Compiler Error for casting un-related types, if it does not throw an ClassCastException at runtime.

    No, it is not an error in the mock exam! The code compiles successfully and when the code is executed no exceptions are thrown at runtime and "15true" is printed.

    Hope it helps!
    Kind regards,
    Roel
     
    Julie P Chen
    Greenhorn
    Posts: 6
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thank you for the replies thus far. I still have questions.

    If I understand correctly, the principle is that we can cast a reference variable to any interface without compiler error (though, may throw CCE if they are un-related) because interface is inherently non-final.
    If that is the case, this example would also compile just fine if the interfaces (CanClimb and HasClaws) are replaced as abstract classes, since abstract classes are also inherently non-final.
    Meaning that in this example, the java.lang.Object (koala) reference variable can be cast to CanClimb abstract class, and canClimb reference can be cast to HasClaws abstract class.

    However, if we assume the same principle on regular non-final classes, it may not always compile.

    For example: //Chapter 5, p283 of the book OCA Study Guide



    SO this principle does not work for regualr non-final classes, but only for interfaces and maybe abstract classes?
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Julie P Chen wrote:If I understand correctly, the principle is that we can cast a reference variable to any interface without compiler error (though, may throw CCE if they are un-related) because interface is inherently non-final.

    That's correct!

    Julie P Chen wrote:If that is the case, this example would also compile just fine if the interfaces (CanClimb and HasClaws) are replaced as abstract classes, since abstract classes are also inherently non-final.

    No! You are incorrect. There is one very big difference between interfaces and (abstract) classes: an interface can extend from multiple interfaces whereas a class can implement multiple interfaces but can extend only from one class. And that's very important! With classes it doesn't matter if the classes are final or not, the only thing that matters is if the classes belong to the same class hierarchy. So if one class is the superclass of another class, you can cast between both classes; otherwise you'll get a compiler error. Consider this class hierarchyIf you have an Animal reference variable, it can refer to an Animal object, a Cat object, or a Dog object. So you can cast an Animal reference variable to Cat or Dog. But if you have a Cat reference variable, it can refer to a Cat object or maybe a BigCat object (if BigCat is a new class which extends from Cat), but it can never refer to a Dog object. So if you try to cast a Cat reference variable to Dog, you'll get a compiler error!

    With interfaces it's a totally different story. Using an interface you can force classes from completely different class hierarchies to implement the same set of methods. For example consider this class and interface hierarchySo that's why you can cast between interface types without getting a compiler error. A Flyable reference variable can refer to an instance of a class which implements 10 other interfaces.

    When casting between a class and an interface, it gets really interesting. When you have a non-final class (ClassX), you can cast between an interface (InterfaceX) and ClassX (or the other way around) without getting a compiler error. This code snippet compiles successfully (but throws a ClassCastException at runtime)But if the class is final (ClassY) and doesn't implement InterfaceY, the compiler knows the InterfaceY reference variable can never refer to a ClassY instance and therefore gives a compiler error.

    If you still have doubts about casting, I suggest you carefully read the topics I mentioned in one of my previous posts. These topics have excellent explanations with a bunch of code snippets and cover everything you need to know about casting.

    Hope it helps!
    Kind regards,
    Roel
     
    Jeanne Boyarsky
    author & internet detective
    Marshal
    Posts: 35279
    384
    Eclipse IDE Java VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Logged that the explanation for D is incorrect. It should be that an interface can be implemented by a class that extends Object.
     
    Julie P Chen
    Greenhorn
    Posts: 6
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi, Jeanne, do you mean "an interface can be CAST by ANY classes, including a class that extends Object in the question"?
     
    Jeanne Boyarsky
    author & internet detective
    Marshal
    Posts: 35279
    384
    Eclipse IDE Java VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Yes. For example this works.



    Casting works like instanceof. (This gets into OCP territory, but basically an interface can be implemented by a subclass so the compiler has no way of knowing if it is ok).
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Jeanne Boyarsky wrote:Yes. For example this works.

    For clarity, "it works" means "it compiles successfully, but throws a ClassCastException at runtime".
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Julie P Chen wrote:"an interface can be CAST by ANY classes, including a class that extends Object in the question"?

    It all depends if the class is final and if it implements the interface. Let's have a look at all possible alternatives:

    1/ non-final class which does not implement the interface
    Casting between the interface and the class (or the other way around) will not give a compiler error, but throws a ClassCastException at runtime

    2/ non-final class which does implement the interface
    Casting between the interface and the class (or the other way around) will not give a compiler error and no exception is thrown at runtime

    3/ final class which does not implement the interface
    Casting between the interface and the class (or the other way around) will give a compiler error

    4/ final class which does implement the interface
    Casting between the interface and the class (or the other way around) will not give a compiler error and no exception is thrown at runtime

    Hope it helps!
    Kind regards,
    Roel
     
    Jeanne Boyarsky
    author & internet detective
    Marshal
    Posts: 35279
    384
    Eclipse IDE Java VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Roel De Nijs wrote:
    Jeanne Boyarsky wrote:Yes. For example this works.

    For clarity, "it works" means "it compiles successfully, but throws a ClassCastException at runtime".

    Well, yeah. I figured the case where it runs without blowing up wasn't the one Julie was puzzled about. Thanks for being thorough!
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic