Approach 1
AppMain.java
A obja = new A(new B());
RandomClass.java
B b;
pubic A(B b){
this.b = b;
}
Approach 2
AppMain.java
B objb = new B();
A obja = new A(objb);
RandomClass.java
//same code
Is approach1 and approach2 same?
With one minor difference, the two approaches are the same (except you would need new A(new B()) instead of new A(new B) in the first approach). The difference is that in the second approach you end up with a separate reference (the variable objb) to the B object that is supplied to the A constructor.
new B is a compiler error. Approach 1 therefore fails, approach 2 does not - they are not the same.
If you intended that to be new B() but you were a little careless in posting the question - then these are entirely the same. new B() means: Make a new B object, and this expression then evaluates to a reference that points at this newly made object. With new A(new B()) you then pass a copy of this reference to the A constructor. With B objb = ... you assign a copy of this reference to a local variable, and then invoke the A constructor, handing a copy of this reference to it.
That boils down to the exact same thing, in other words.
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
Ok.. So,
When you have a hierarchy of classes such as
public class A {...}
and,
public class B extends A {...}
...When you create objects, what is the difference between:
A object = new A();
A object = new B();
B object = new B();
Thank you for your time.
public class A
{
public void methodA(){}
}
public class B extends A
{
public void methodB(){}
}
I hope this can demonstrate the difference.
A obj = new A();
a.methodA(); //works
A obj = new B();
obj.methodA(); //works
obj.methodB(); //doesn't work
((B)obj).methodB(); //works
B obj = new B();
obj.methodA(); //works
obj.methodB(); //works
A object = new A();
You are creating an A instance in a reference of type A. You may can access only A methods/properties and parents methods/properties.
A object = new B();
You are creating B instance in a reference of type A. In this way object could behave in a polymorphic way, for example if you make object.method() and method is overriden in B then it will call this override method. You have to take care in not to break the Liskov Substitution Principle. You may can access only A methods/properties and parents methods/properties. This is the preferred way when you only need supertype contract.
B object = new B();
You are creating a B instance in a reference variable of type B. You may can access only B methods/properties and parents methods/properties.
A line like
A var = new B();
is kind of a shorthand for two separate steps.
A var; // (1) Make a variable of TYPE A.
var = new B(); // (2) Make an object of CLASS B, that from now on may be
// referred to by the variable var.
So a variable has a TYPE, and an object has a CLASS. Often they match up. The type of a variable is often actually a class, although not necessarily. It's important to understand the difference between the type of a variable, and the class of the object that the variable refers to.
An object typically belongs to more than one class. If class B extends class A, that means that all objects of class B are also objects of class A. And all objects of any class at all are also objects of class Object. In other words, when we say that an object is a B, that's more specific than saying it's an A. Just like when we say that Yogi is a bear, that's more specific than saying Yogi is an animal, because all bears are animals.
So a variable of type A can indeed refer to an object of class B, if A is a class that B extends. But if you've got a variable of type A, you can't use it to do things that are specific to objects of type B. For example, suppose class A has a method called display() and class B has a method called explain(). The compiler will let you call display() on a variable of type A, but it won't let you call explain(). If it did, it would be risking trying to call explain() on an object that's not actually a B, which would fail.
So whenever there are methods that class B defines, you'll need a variable of type B in order to be able to call them. Of course, you can also use that same variable to call the methods that are defined in class A. In a sense then, if class B extends class A, then a variable of type B is more powerful than a variable of type A - you can do more stuff with it.
So the question arises - why would I ever want to write
A var = new B();
when a variable of type B would be more powerful than var in this example?
The short answer is that it communicates to people looking at the code. It says, "yes, I know this variable refers to a B, but I actually only intend to use the methods provided by class A. This can actually be helpful to someone trying to understand your code, or to maintain it.
There are also cases where it can make a real difference to method calls involving that variable. Suppose there's another class C, which has two methods with the same name but slightly different signatures, like this.
public class C {
public void process(A arg){
// Do some stuff
}
public void process(B arg){
// Do some other stuff
}
}
In this particular case, the version of process that gets called depends on the type of the variable, not the class of the object. So if you write
C processor = new C();
A var = new B();
processor.process(var);
this will call the first version of process - the one with A in the signature. Because of the type of the variable. But if you write
C processor = new C();
B var = new B();
processor.process(var);
this will call the second version of process - the one with B in the signature.
A object = new A();
object of type A (you can access fields or method from A)
A object = new B();
object of type A (you cannot access fields or method from B, only from A)
B object = new B();
object of type B (you can access fields or method from A and B)
A object1 = new A();
A object2 = new B();
B object3 = new B();
object1 is declared as a reference to an A object. Since class B extends class A, it could be set to either or (new A() or new B() would be valid).
object2 is declared as a reference to an A object, but is actually a B object. Say the B class has a method called eatFood(). If you tried to access that method with object2.eatFood(), the compiler would throw an error because the eatFood method is only in the B class. Even though the object is actually a B object, the compiler thinks it is an A object due to the type declaration. To access the eatFood method, you would have to typecast it: ((B)object2).eatFood().
object3 is simply a reference to a B object, and in reality IS a B object. It could access A methods as well as B methods.
A object = new B();
This declares that object will refer to an object of class A or any of its subclasses (when it isn't null). The compiler will treat it as an object of type A, so you can only access methods and fields that are declared for A (or one of its superclasses). It also means that you can later assign it to any other object that is of class A or a subclass:
A object1 = new B();
B object2 = new B();
// reassign later
object1 = new A(); // legal
object2 = new A(); // ILLEGAL
class C extends A { ... }
object1 = new C(); // legal
object2 = new C(); // ILLEGAL
So the initial declaration declares object as having type A. But its initial value is an object of type B, which is OK because B is a subclass of A.
That should explain the difference between your second and third examples. The difference between the first and second is simply that (at run time) the first creates a new object of type A and the second creates a new object of type B.
I wrote this code:
class A {
int a;
void method() {
System.out.println("Overridden method of Class A called!");
}
void method2() {
System.out.println("Normal Method of Class A called!");
}
}
class B extends A {
int b;
void method() {
System.out.println("Overridden method of Class B called!");
}
void method1() {
System.out.println("Normal Method of Class B called!");
}
}
class C {
public static void main(String[] args) {
A a1 = new A();
B b1 = new B();
a1 = b1; // ***Line 1***
System.out.println("After referencing!");
a1.method();
a1.method2();
A a2 = new B(); // ***Line 2***
a2.method();
a2.method2();
}
}
Line 1 and Line 2 are in the code above marked by comments
Now, I have some idea about the physical significance of Line 1, but what exactly does Line 2 mean?
How is memory being allocated to object 'a2' of Type A? What is the nature and behaviour of such object and how does it differ from normal instantiation? Does Line 1 and Line 2 convey same meaning? If so, how? If not, how are they different because apparently they give same output.
Always try to code to an interface than to the concrete implementation unless the cases where you find it appropriate (like say classes from Swing, where UI components have concrete implementation but you can override it to get better UI or UI of your choice).
Now considering your case, if I was doing this inheritence just for different behaviours ie different method implementations, i would have preferred an interface 'I' which is implemented by both class A and B. And thats where it starts making more sense.
Above explains the design perspective.
Now from coding perspective. A super class an always reference a subclass object. But when you access a method, its the method of the object which is called but the method of reference type.
A a1 = new A();//Object of A in heap which is referred by reference of A
B b1 = new B();//Object of B in heap which is referred by reference of B
a1 = b1; // ***Line 1*** Here super type(a1) is referring to subtype b1. So actual object is that of class B.
System.out.println("After referencing!");
a1.method();//method from actual object is called ie b1
a1.method2();//same
A a2 = new B(); // ***Line 2*** again object created in heap is of type B but its referred by super type A
a2.method();//and hence,method called is from B class not from class A
a2.method2();
They are the same. In Java all object references maintain the same amount of memory. So the same Object reference's memory space can point to any Java Object. The compiler enforces that you only assign a reference A to point to an Object that is of a class that extends A. In both the above cases you have a reference (pointer in C) of type A that is being pointed to an instance of class B.
a2 is a reference type [of type A] and it is referencing to object of Type B. Thats it, nothing more than that.
Yes Line1 and Line 2 are same thing. Just different ways of doing same thing.
The are both equivalent, but only difference is that in the first you are unnecessarily creating an of A (new A();) which you just throw away.
A a1 = new A(); // new A() should not be done here
B b1 = new B();
a1 = b1; // ***Line 1***
It would be better to do it as follows -
//A a1 = new A(); // new A() should not be done here
B b1 = new B();
A a1 = b1; // ***Line 1***
They are similar because in both cases, you are instantiating an object of B (new B();), and creating a variable of type A to refer to that instance.
Both the lines are just similar to the following
Object obj = new SomeClass();
But in the Line1 one extra object of type A is being created.
So with
A a1 = new A(); // a new object
B b1 = new B(); // another object
a1 = b1; // make a1 point to the b1 and lose the reference to original `A` type object
A a2 = new B(); // create a new `B` object and assign it to reference of `A` type.
So essentially the are same (other than the extra object in line1)
But
These two lines are internally using the concept of polymorphism.
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.