Assume class B extends class A and I want to declare a variable for B. What is more efficient and why?
B b
OR
A<B> b.
You are confusing two different concepts.
class B extends A {
}
means that B is an A.
If you have something like A<B> it means that you class A is defined as
class A<T> {
}
meaning that you class A is a generic class.
For example (over simplified) you have
class List<T> {
}
So if T takes the value String you would have List<String> meaning a list of Strings
So A<B> does not mean that B extends A.
You should use B b.
Use B b. A<B> is a template class that uses B as a type, for example:
List<String> is a list of strings, so List<B> would be a list of B objects.
WeakReference<String> is a a weak reference to a string, so WeakReference<B> would be a weak reference to a B object.
If B extends A then I would use type A as much as possible.
A widget = new B();
This lowers the assumptions other parts of the code may make on your implementation.
I think it's not a matter of efficiency but of usage. If a pure A object isn't meant to use B, why would you want it to be A<B> b?
Your declarations don't do remotely the same thing. The first declares an object of type B, while the second declares an object of type A<T>, where T is a type parameter whose slot is filled by the type B.
Neither declaration is more efficient than the other.
But A<B> b doesn't declare a reference of type B, it declares a reference of type A that is templated on type B.
Unless A is a generic class, the second form is illegal.
Related
If I would have a variable a declared by A a and a method m with void m(B b). Is there any way that calling m(a) would work? Or can this never work because a is of type A and b of type B.
If A extends B, it can be passed as argument to that function. If not and A contains values suitable for B you have to create an instance of B and fill it with the required values of the instance of A.
This works if A is a subclass of B
This could work in two scenarios:
When A is a B, i.e. inheritance or interface implementation, or
When A and B are primitive data types, and an implicit conversion exists from A to `B.
Here is an example:
void m(long b) {
...
}
int a = 123;
m(a); // This compiles and runs correctly
This can be possible when A is a subclass of B or we can say A extends B,
this is known as inheritance in programming language, in this A will be a child of the class B and inherit all its properties
you can check it from the link below
https://www.tutorialspoint.com/java/java_inheritance.htm
Let us consider we have two classes A and B. B is a sub class for A because B extends A. If We create an instance of A Class and assign that in to a A type will contains all the properties of A. Similarly when I create an Instance of B and assign it to B type will get all the properties of B along with properties of A because it is inheriting from A. According to above lines instance of A contains properties a few as compared to properties contains to instance B. That means Instance of B is Bigger than Instance of A as casting should be explicit when narrowing implicit when widening. According to my theory Instance of B is bigger we are trying to store it in A type we need conversion.
A a1=new (A)B();
The above conversion is taking place implicitly. But my question is how it is implicit, Instance of B is bigger we are trying to convert that to small type which is A. How this is possible???
Answer me with examples thank you in advance.
You are thinking in terms of object size, but in Java, non primitive types are never contained, only referred to. Thus, your code is casting the result of new B(), which is of type "reference to B", to type " reference to A". Since all references are the same size, no data is lost in the cast.
So, I really don't understand your question. I just think you are confused about what happens to the class B members when a upcast to his super class is made. In that case, you ended up with a instance of A wich means that Object type is A and non of B stored data will remain.
In Java, with
B b = new B();
A a = b;
one defines references b and a. Under the hood, references are implemented with pointers, and thus, all references are the same size. Of course, an instance of a B might indeed require more memory than an instance of A (I take it, this is what you mean by "bigger").
By the way, in C++ this is not the case.
B b();
does define an object, not a reference, and therefore
A a = b;
in C++ is indeed not allowed.
Think about this:
class Animal{
public void eat(){}
}
class Monkey extends Animal{
public void climbTree(){}
}
I can now do this:
Animal someAnimal = new Monkey(); //This is ok. (Create a Monkey and identify is as an Animal)
someAnimal.eat(); //This is ok too. (All Animal objects can eat)
someAnimal.climbTree(); //Not ok. Java sees someAnimal as a general Animal, not a Monkey yet.
From the above example, someAnimal is a Monkey object which is stored within a variable of higher hierarchy (Animal).
The object itself is perceived as the a more general class (The Animal class) and I don't think an implicit casting is done here since all Monkeys are already Animals (but not the other way round).
Explicit casting can be done when you want to let the compiler knows that the object actually belongs to a more specific class. For example:
((Monkey)someAnimal).climbTree(); //This is ok. Inform Java someAnimal is actually a Monkey which knows how to climb.
Example :
Class Employee {
private String name;
private double Salary;
//getter & setter
//mutators to increase salary etc;
}
class Manager extends Employee {
private double bonus;
//inherits methods from superclass
// sub class specific methods
}
Employee e = new Manager(); //is fine as manager is also an Employee...
The prefixes super and sub come from the language of sets used in theoretical computer science and mathematics. The set of all employees contains the set of all managers, and thus is said to be a superset of the set of managers. Or, to put it another way, the set of all managers is a subset of the set of all employees.
~ From core java series
hope this helps...
The cast isn't actually implicit like you're saying. What is actually happening is this:
B b1 = new B();
A a1 = (A)b;
The (A) is an explicit cast, what's more important is to stop considering the size of things in the sense that the size of B is different from the size of A. This can be an implicit assignment because B IS-A A, so using A as an interface for B is completely safe, because we know that B has at least the same members as defined by A.
So the perfectly safe (and not erroneous) method of doing this is simple:
A a1 = new B();
Done!
Let there be two classes defined as follows:
Class A{
int a;
}
Class B{
int b;
}
A and B are two unrelated classes. Is there anyway I can cast an object of A to B? If yes, please explain the various options I have.
You can do
Object b = new B();
A a = (A) b;
But this will throw a ClassCastException at runtime.
Instead you can use a copy Constructor
class B {
public B(A a) { ... }
public static B toB(A a) { return new B(a); }
}
And then you can do
B b = new B(a);
or
B b = toB(a);
You can do an upcast to a common super type, followed by a downcast
(Dog)(Pet)aCat
Of course, Object is the supertype of any type, so we can use it to cast between any 2 types
(Apple)(Object)aCat
Usually, this makes no sense, and it will cause runtime exception. But it may be helpful in some generic cases. For example, Supplier<Integer> and Supplier<number> are "unrelated"; as a matter of fact, they are mutually exclusive, i.e. the intersection is empty, or, no object can belong to the two types at the same time. Nevertheless, we may want to cast Supplier<Integer> to Supplier<Number>, due to lack of variance in Java, combined with the existence of erasure. See this case study.
You can't. That would break a fundamental principle of object-oriented programming.
Though JAVA allows you to type cast object across unrelated classes i.e. which are not in class hierarchy. This is allowed because of the below case
String s = (String)list.get(1);
Well list can certainly contain different type of object and while calling such a method it could return String as well.
Coming to your question you will succeed in typecasting but at runtime you will get ClassCastException .
You can type cast object B to type A iff B IS-A A that means B is a subtype of A. If both are not in a hierarchy then type casting them does not make sense. just like you can not type cast an Animal type to Furniture type.
if:
interface I{}
class A implements I{}
class B extends A{}
class C extends B{}
A a = new A();
B b = new B();
Why a = (B)(I)b; is correct
but b = (B)(I)a; is false?
I find casting to be very confusing, what is the best way to understand if I can down cast or up cast an object?
Your class hierarchy looks like this:
Object x can be casted to class Y, if runtime type of x is subclass of Y. Or, in other words, if there is a path from runtime type of x to Y. By "runtime type" i mean the type of object (the one used when constructing object) as opposed to type of variable (the one from variable declaration).
This is valid:
b = new B();
(B)(I)b;
Object stored in b has type B. It's casted to I and then back to B. B is a subclass of both of them. Cast to I doesn't actually do anything and is meant only to confuse you.
However, neither of those is valid:
a = new A();
(B)(I)a;
(B)a;
They will both fail with exception: java.lang.ClassCastException: A cannot be cast to B. a has type A which is not a subclass of B. There is a relation between A and B, but it's in the opposite direction - B is a subclass of A.
For more detailed explanation see here: http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
The only thing of relevance to answering the question in your coding sample is the following:
class B extends A{}
This means that B is a subclass of A. Subclasses can be cast to super class types, but super class cannot be cast to subclass types.
Therefore, A cannot be cast to type B.
Why? Think about the logic this way:
is a type of Programming_language, but Programming_language is not a type of
In Java, suppose I have 3 classes, C extends from B which extends from A.
class X {
interface A {}
interface B extends A {}
interface C extends B {}
void f(A a) {}
void test() {
C c = new C()
B b = (B) c;
f(b);
}
}
If I do something like this as shown in test() above:
C c = new C()
B b = (B) c;
f(b);
f() accepts b as type C since C and B both extend from A. I wanted f() to receive b as type B and not type C.
Is there anyway to force this upcasting?
f() will always receive something typed as A (despite under the covers it's actually a B or C, and can be downcast appropriately).
You can define an additional f() thus
f(B b);
and if necessary
f(C c);
and the correct one will be called depending on the class of the argument. i.e. the compiler determines which function is called depending on the type of the argument. This is different from a dynamic dispatch (or polymorphism) which would occur at runtime.
Note that your cast in the question is redundant. You can write:
C c = new C()
B b = c;
f(b);
since C extends from B, C is a B.
You seem to be confused about the difference between compile time type and runtime type.
You are creating an object (pointed at by the references c and b) of type C, and it will stay a C, because it is impossible to change an object's runtime type and therefore behaviour; by casting you can merely change its compile time type, which affects how the compiler treats it.
Can you give some more information about the concrete problem you're trying to solve? Most likely there is a way to achieve your goal by changing the design.
I wanted f to receive b as type B and not type C.
A C is a B is an A.
Inside of f, f only sees the A part of its parameter a If f calls a public A function that is overridden in C, the C override is called.
That's how virtual functions work. The idea being, the object referred to is really a C, so it should exhibit C behavior. If you want B behavior, pass a B instance, not a C instance.
If 'C' and "B' should have the same behavior, don't ovveride that behavior in C.
Why do you want to do this?
Your question does not make sense. What do you mean by "f accepts b as type C"?
f accepts b as type A, since the method signature says "A". If you invoke methods on b, they will be invoked on C if C overrides them. But this is standard behaviour in Java (all methods are like virtual methods in C++), and there's no way to change it.
Maybe you can describe your actual problem, then we might be able to help.
Your issue can be resolved by understanding the difference between REFERENCE type and INSTANCE type. When you cast you C object as a B, you only change the reference type - the actual instance of the object is still a C object - this should be quite obvious if you look at your object in debug mode. Changing the reference type only impacts how the compiler handles/perceives the code - runtime behaviour should not be affected. Any method call on an C object will always invoke C's method (regardless of whether or not the object has been casted to something else). If you overode a method from B and want to invoke B's version of the method, then you will need to create a B instance.
The fact that you can pass any subclass of A as a parameter of f(A a) is inherent to OO in Java, there's no way you can go around this. If C extends A, you can always use it where an A is expected.
you can use reflection to check if the parameter is of class A:
public void f(A a) {
if (a.getClass() == A.class) {
// ok, go on
}
else {
System.err.println("The parameter is not of class A!");
}
}
don't know if that's what you want, but it may be helpful.
The fact your code has a reference to an A doesn't mean the object being pointed too is an A. If it's a a C it remains a C. The reference in your source only limits the available methods in your source. Casting is only necessary because sometimes one needs a method on a different type and we need to trick the compiler so it let's us start using methods on the castes to type. Naturally the cast can fail at runtime if the attempt us invalid.
In upcasting and downcasting the object first upcast then downcastenter
class A
{
}
class B extends A
{
}
Class M
{
psvm(String ar[])
{
A a1= new B();
B b2=(B)a1;
}