A is an abstract superclass of the concrete classes B and C. Constructors of all
three classes do not take parameters. The following variables are defined:
A a;
B b;
C c;
Which one or more of the following assignments will result in an error at
compile time?
(i) a = new C();
(ii) b = new C();
(iii) a = new A();
(iv) b = (B) new A();
Any help is appreciated
A is abstract so ANY attempt to create an A outright will fail. Also, the relationship between B and C is not clearly defined but I am betting the second case will fail as well unless B is a superclass of C.
Because A is an abstract superclass of B and C, A cannot be initialized. However, its subclasses can be stored in an object of the type of the superclass (A), since it shares or defines the methods contained in A.
Should be enough to figure it out.
Related
I am preparing for java certification and unable to find any concept or logic behind this.
Can anyone help me understanding the concept of multiple typecasting. I can understand the one level of type casting but I am not getting any information for these conversions.
Here is the sample I am trying to understand.
interface I{
}
class A implements I{
}
class B extends A {
}
class C extends B{
}
A a = new A();
B b = new B();
Now option 1 don't have any error at compile time or runtime, while 2nd option is having error. I run it in eclipse but unable to understand the logic behind this.
1. a = (B)(I)b;
2. b = (B)(I)a;
Your question is a bit vague but I'll see if I can help.
So you have your interface I and classes A, B and C.
You can now do things like these:
I i1 = new A();
I i2 = new B();
I i3 = new C();
This is possible because, by inheritance, all the classes A, B and C implement I.
You can also do
A a1 = new B();
A a2 = new C();
for almost the same reason (difference being they are extending A rather than implementing an interface).
You probably guessed by now that you can also do
B b1 = new C();
What you can't do is something like
B b = new A(); // Type error
C c = new B(); // Type error
B b2 = (B)new A(); // ClassCastException
This is not possible since the type A does not extend from B.
In general you don't need to explicitly type cast in these cases.
I i = (I)new A(); // <- not necessary
It can be necessary in the opposite direction however:
I i = new B();
B b = (B)i; // <- cast is needed.
This works if and only if i is actually of type B (or C). If the object i is not of type B or a type that extends from B you will get ClassCastException.
Now for your question
Both your two options are a bit strange. Double casting is not something you would normally do. the cast to I is unnecessary.
With that said, 1) will work and 2) will not. Your object b cannot be assigned a because A does not extend from B.
Edit
To be clear, when you instantiate an object, for example
A a = new A();
The actual object (I'm going to call it o) is an instance of class A. You also have an object reference called 'a' which is typed as A which refers to the object o.
When you assign other object references, the type of the actual object doesn't change. When assigning a reference, the type of the object must be the same type as the reference or of a type that inherits from the referred type.
For example, you can assign a reference of type I:
I i = a;
This assigns the reference i to the same object that a refers to which is the object o. Note that o is still of type A.
System.out.println(i instanceof A);
will print
true
I have a broad question regarding Java casting via classes. Let's say I create 4 classes (well 3 classes and 1 interface), Interface A is the super interface I guess you could say and Class B implements A (meaning that it is the subclass of the interface A) and C extends B and then D extends C.
Let's say that I have a driver class in which I initialize the following like below:
A myA;
B myB = new B();
C myC = new C();
D myD = new D();
//I want to cast now!
myB = (B) myD;
myC = (D) myA;
myD = (C) myB;
When are these fabricated objects actually compilable? I'm having a bit of a difficult time understanding the rules between casting. I do kind of understand Down-casting and how it's not permitted, but I guess class casting is still a concept that sort of confuses me.
The thumb rule is that if an object B is of type A, then it can be casted to A. In you example B implements A so B is of type A. You can cast any B object to A. Since C extends B, C is of type B as well as of type A. So C objects can be cast to A or B.
Wanted to add as comment, but coz of limitation, had to add it as answer:
1) Rule is Child can inherit what father/parent has, but not reverse.
2) Child can be stored as parent, but not reverse.
That makes myD =(C)myAB; uncompilable as myD extends C (which extends B-->A)
So when you create
B myB = new B();
If I try to explain in non technical terms, Then myB knows everything about B and A, but it does not know what is below. It can see and identify itself with anything above it in following hierarchy:
A
B
C
D
So lowest one D can be casted to anything that lies above it.
1) myB = (B) myD;
With rule state above, D is below B and hence can be assigned to B.
2) myC = (D) myA;
Here you have casted interface to D, and hence in compile time, D can be assigned to top level C.
3) Here myB (which in that statement is typecasted to C in compile time) can't be assigned to D at compile time (although it is instance of D which is lower in hierarchy) but when you are compiling, you don't have runtime instance available. So below will fail:
myD = (C) myB;
I assume I have not confused you further here.
If you have two different classes A and B, and B is a subclass of A, you cannot cast as follows:
A a = new A();
B b = new B();
A newA = (A)b;
Is there a way to enable the above code to work (no alterations to the above code) without the JVM throwing a ClassCastException?
------------EDIT----------
Sorry, I made a mistake in the code in the above question. The correct version is below:
A a = new A();
B b = new B();
B newB = (B)a;
B already has an is-a relationship to A. You don't need to cast it....You can throw a B at any method or reference that expects/points to an A.
Based on your edit -- there is something wrong with your design if you want to do this. While a B is-a A, the opposite is NOT true. An A is not a B. In other words, since B extends A, it probably has methods/properties on it that are NOT defined on A. If you cast an A to a B, then methods that accept that reference might try to invoke a method it believes is on the instance, since you told the compiler that it got a B, when in reality the underlying A does not have the required method.
Casting here will only lead to pain and failure.
I think you can simply assign:
A newA = b;
If B is a subclass of A the above should work, and the cast would be unnecessary:
A a = new A();
B b = new B();
A newA = b; // no need to cast!
With new code, no you can't do that. You'd have to create a new object:
B newB = new B(a);
or
B newB = B.of(a);
A non-abstract non-leaf class should generally be avoided anyway. Also, since 1.5 (released 2004), there shouldn't be much of the casting syntax about.
I have a parent class class A and a child class class C extends A.
A a=new A();
C c=(C)a;
This gives me error. Why?
Also if my code is
A a=new A();
C c=new C();
c=(C)a;
This works fine.
Now what all methods can my c variable access..the ones in C or the ones in class B?
It's giving you an error because a isn't an instance of C - so you're not allowed to downcast it. Imagine if this were allowed - you could do:
Object o = new Object();
FileInputStream fis = (FileInputStream) o;
What would you expect to happen when you tried to read from the stream? What file would you expect it to be reading from?
Now for the second part:
A a=new A();
C c=new C();
C c=(C)a;
That will not work fine - for a start it won't even compile as you're declaring the same variable (c) twice; if you fix that mistake you'll still get an exception when you try to cast an instance of A to C.
This code, however, is genuinely valid:
A a = new C(); // Actually creates an instance of C
C c = (C) a; // Checks that a refers to an instance of C - it does, so it's fine
Here's a nice youtube video http://www.youtube.com/watch?v=jpFij6RD7CA which demonstrates the same. Below is a full textual information for the same.
“Upcasting” means moving subclass object to the parent class object. “DownCasting” is opposite to “Upcasting” moving the parent object to the child object.
“Upcasting” is perfectly valid but “Downcasting” is not allowed in .NET. For instance below is a simple “Customer” parent class which is further inherited by a child class “GoldCustomer”.
class Customer
{
}
class GoldCustomer : Customer
{
}
Below is an “upcasting” code where the child parent class gold customer is pushed to the customer class.
Customer obj = new GoldCustomer();
Below is a sample of “downcasting” code where parent class object is tried to move to a child class object, this is not allowed in .NET.
GoldCustomer obj = new Customer(); // not allowed illegal
In java there is concept that without upcasting u can't perform downcasting
A a=new A();
C c=(C)a;
in this case u try to perform downcast with out upcasting
A is not a subclass of C hence you cannot cast it down.
While casting the objects what we need to keep in mind is to apply is a relationship to the instances.
Like in your example C is A but A is not C.
So in your case,
A a=new A();
C c=(C)a; // classCasteException occures.
I think this might help you.
A class C has a void method m with no parameters. Another class D extends C and overrides m. Each class has a constructor with no parameters. In each of the following, say whether it is legal, and if so, which definition of m will be used.
i) C x = new D();
x.m();
ii) D x = new C();
x.m();
I think i is legal, and ii is not illegal. Not sure how I get my head around this question, any hints are welcome.
The best way to answer the question is to write some code and see what happens. Use System.out.println("method called from C"); in your implementation of m to tell which implementation is called. Having said that, the whole point of overriding a method is so that the new implementation will get used. If you object is of type C then Cs method will get called. If you object is of type D then Ds method will get called regardless of what type the reference is.
The first answer:
C x = new D();
is legal because and object of type D is a C as well (because D extends C).
The second answer:
D x = new C();
is not legal because a reference to D cannot hold an object of its supertype C.
Yes, you are right.
(i) is legal, and it will be D's m method that gets run (this is called polymorphism).
(ii) is illegal, and will not even compile, because D is not a supertype of C (in fact, it's a subtype). We could make it compile by writing it as:
D x = (D) new C(); x.m();
but then it would fail at runtime with a ClassCastException
Try to think of inheritance in terms of "is a" relationships.
If D extends C then that means each D is a C, but does not imply that each C is a D.
To apply that thinking, translate the question into an "is a" question.
C x = new D()
is a statement that requires that a new D() is a C.
In String s = new Object(), ask yourself "is a new Object() a String?" What about vice-versa?
Good luck learning OOP.
i) is legal, ii) is not. It's very easy to see if you use a metaphor, say class C is Animal and class D is Dog, method m() is makeNoise.
Now it's legal to have a variable of class Animal and assign a Dog to it (because a dog "is a" animal), but it's not legal to instantiate an Animal and assign it to Dog since the Dog is more specific than Animal (we can not say an animal "is a" dog).
Now for the method: the method is always called on the runtime type, not on the variable type (all method calls are so-called virtual in Java), so in case i) it calls the m() method of class D, not of class C.