I have a class structure like this:
Interface A extends X
Class A_Impl implements A
Interface B extends A
Class B_Impl extends A_Impl implements B
My webservice client returns object of A and I need some parameters from B. So I do is this:
A myA = (A) webservice.getA();
B myB = (B) myA;
But this always throws the ClassCast exception:
java.lang.ClassCastException: A_Impl cannot be cast to B
Am I doing something wrong here ? How can I get some params from B class.
If you have a reference to an object that doesn't implement B, there is no way to cast it to a B. Full stop.
Imagine if it was possible. Then what would this print?
interface A {
int getNumberOfLives();
}
interface B extends A {
boolean isOrange();
}
class A_Impl implements A {
int getNumberOfLives() {return 9;}
}
public class Main {
public static void main(String[] args) {
A a = getA();
B b = (B)a;
System.out.println(b.isOrange() ? "Is orange" : "Is not orange");
}
static A getA() {return new A_Impl();}
}
You cannot get any properties of B when you have an instance of B's supertype A, or any subtype of that other than B. For example, if you wanted to get the value of a field x that is a member of B, but your object is only an A, the field is not even present in the object. So what would the value of it be? That is the reason you can't cast in this direction. If you wan't to access the object like an instance of B, you have to change your webservice.getA() to something that actually returns a B (or a B_Impl)
Related
So I don't know if this is possible I've tried searching it but maybe my search terms are off. Basically I'm wondering, is there a way to create a generic function/method in a super class that returns the downcast object.
class A {
public <downcasted type (in this example B if called from a B instance)> test() {
return this;
}
}
class B extends A { }
B b = new B().test()
basically having "test()" return the B instance as type B even know the function/method is declared purely in the parent class?
I know I can cast the variable, tho having many functions some of which may return Lists of the class type, etc become troublesome. I also realize I could #override the function in B and do a "return (B)this.super()" thing, but again wrapping many functions is tedious and makes makes updating the base classes code more painful.
I also know you can do
"class A<T extends A>"
and then define B as
"class B extends A<B>"
but then if you want to make a "C" that extends "B" it breaks.
So is this type of behavior possible? If so, what is it called and how do I implement it?
An example as to where this behavior could be useful would be any base data structures you want to make extendable like an N-Ary Tree that you extend into oct/quad tree structure and/or an extended class that adds a "Name" and "Attributes" or something for a xml-like node.
Edit:
This seems to work(as far as the linter is concerned), it's a bit more work to implement the base methods but it's got the desired end result as far as I can tell. That said when I attempt to run it, it gives me a "cannot find symbol: class type" error. :S
static class D extends auto {
final Class type = getClass();
#SuppressWarnings("unchecked")
public <T extends type> T test() {
return (T)type.cast(this);
}
}
static class E extends D { }
static class F extends E { }
static {
D d = new D().test();
E e = new E().test();
F f = new F().test();
}
Update
There is a simpler way, which seems to work:
class Alpha {
#SuppressWarnings("unchecked")
<T extends Alpha> T test() {
return (T) this;
}
}
class B extends A { }
However, that does not support method chaining.
Original post
You need test() to return a subtype of A, rather than A itself. In order to do this, the signature of the A class could be this:
class A<T extends A<?>> {
#SuppressWarnings("unchecked")
public T test() {
return (T) this;
}
}
If you create a class B extending A, you will need B.test() to return an instance of B, without needing to override test() returning a specific type. You could then do something like this:
class B<T extends B<?>> extends A<T> { }
Now T is a subclass of B, and because test()'s return type is T, it will return a B instance. Further subclassing can be done in the same way:
class C<T extends C<?>> extends B<T> { }
And statements like this will work:
C<?> c = new C<>().test();
I have a ModelDecorator helper. I want it to have the following public API
class ModelDecorator<T>{
public static <T> ModelDecorator<T> create(Class<T> clazz);
public <SUPER> T from(SUPER fromInstance);
}
So, given classes A, B extends A, it can be used like this:
A a = new A();
B b = ModelDecorator.create(B.class).from(a);
But I want to have bounds on T and SUPER, so I make sure that only subclases can be instantiated using the API. At this moment, I can do:
C c = new C();
B b = ModelDecorator.create(B.class).from(c);
Where B DOES not inherit from C.
Any ideas? Thanks
The only way I see for constraining your type parameter T to extend the type parameter S is to put those definitions into the class definition:
public class ModelDecorator<S, T extends S> {
public static <S, T extends S> ModelDecorator<S, T> create(Class<T> clazz) { ... }
public T from(S instance) { ... }
}
With these classes
class A {}
class B extends A {}
class C {}
you now can write the following code:
A a = new A();
B b1 = ModelDecorator.<A, B> create(B.class).from(a); // compiles fine
C c = new C();
B b2 = ModelDecorator.<C, B> create(B.class).from(c); // bound mismatch here
The second B creation now has a compiler error.
Unfortunately you now must explicitely provide the type parameters because the compiler is not able to infer the type A or C from a simple method call create(B.class).
In Android Studio I have the following error:
java: incompatible types: java.lang.Object cannot be converted to
java.lang.String
I think b1 and b2 should be behaving the same, but they are not.
Is there a way to make them behave the same (without changing their type of course)?
Here is the code typed:
public class Test
{
class A<T>
{
T t;
T getT()
{
return t;
}
}
class AS extends A<String>
{
}
class B<T> extends AS
{
}
B<Object> b1;
B b2;
public void test()
{
String t3 = b1.getT();
String t4 = b2.getT();
}
}
The problem is that B is a parameterized type, but b2 is declared to have raw B as its type.
You demonstrate with b1 that B's type parameter is distinct from A's, even though they have the same name, so that B's type parameter has nothing to do with the return type of the getT() method inherited from A<String>. When you use a raw type, however, you get the full erasure of that type, including of its supertypes.
Since's A's type parameter is unbounded, its erasure produces type Object, and therefore this is the type of b2.getT(). Of course, Object is not assignable to String.
You can resolve this in at least two ways:
Don't use a raw type for b2. If you don't care about its type parameter then use B<?>. Or,
Remove class B's type parameter. It's not used for anything in your example, so that would be the cleanest thing to do. Just because its superclass is generic does not mean that B has to be.
I think that B without the template object is an incomplete class as opposed to B<Object>. This is why when you are calling it getT() you are actually calling A.getT().
This why in the code below, only String t3 = b2.getT(); fails to compile.
static class A<T>
{
T t;
T getT()
{
return t;
}
}
static class AS extends A<String> {}
static class B<T> extends AS {}
static class C extends B<Object> {}
static A a;
static B<Object> b1 = null;
static B b2 = new B();
static C c = new C();
static void test()
{
Object tt = a.getT();
String t2 = b1.getT();
String t3 = b2.getT();
String t4 = c.getT();
}
The issue here is that getT() returns the object. What you need to do is implement a method toString() that gives the value of the T Object in terms of a String (or just change the types for t3 and t4 to T so the declaration comes out to T t3 = b1.getT(); and T t4 = b2.getT();).
In addition, you should do the following instead of the code you have for B.
B<T> b1;
B<T> b2;
Note that you need to initialize B to something before you can call b1.anyMethod() or else you'll get a NullPointer Exception.
Without irrelevant pieces, I have:
public interface A {
// contents
}
public class B implements A {
// contents
}
I'd like to follow the dependency interjection pattern by instantiating the object of class B in my main method then passing it into class C's constructor, instead of instantiating it in C's constructor.
public class C {
private final B object;
private int D;
}
public C(A object) {
B = object;
D = object.method();
}
public static void main(String[] args){
C finalobject = new C(new B);
}
Essentially, I want to do something similar to what this question is based on.
I get the error:
C.java:137: error: incompatible types: B cannot be converted to A
C finalobject = new C(new B());
How do I pass B into C's constructor with the interface as the parameter?
I've tried casting it, and I can't instantiate it as the interface in the first place for obvious reasons. I can't pass it in as the object's class type not only because it doesn't fit the specifications I have for how this program has to behave, but I'd like to learn how to do what I've been trying to do.
You're forgetting that there could also be a D, E, F, and G classes that implement A interface. Meaning what you're doing is wrong conceptually. Of course you know what you're passing inside and you know it is an instance of class B, however Liskov's Substitution Principle would suggest that you either deal entirely with B or deal entirely with A depending on what fits the role better. You shouldn't ever need to cast to a derived class.
So that said, your solution is simply the following:
public class C {
private final A object;
private int D;
}
Any methods you need to call in B should be added accordingly to A, and if you don't think that A is suited to have certain methods, then you should ask yourself if you should be passing an A instance to C to begin with.
Hope that helps!
The definition of class C should be:
public class C {
private final A object;
private int D;
}
If you really need a B in C class, you have to change the C constructor to:
public C(B object) {
B = object;
D = object.method();
}
I have a abstract super class A, and a subclass B that extends this class.
public abstract class A {
}
public class B extends A {
}
I have a method that returns type A, but object B
public A fetchType() {
A a = new B();
return a;
}
When I call the fetchType method, I want to actually get object A. In this case, I might have to cast B to A so I get A. How can I do that?
You cannot create an object if the type is abstract.
Here class A is abstract class, which means you will NEVER be able to create object A.
This is not allowed: A a = new A();