views:

49

answers:

2

Good day, I have the following problem: class B extends class A and methods of both are called by another method in another class after instantiating class B (example follows):

public class A{
    //fields
    //constructors
    //methods
}

public class B extends A{
    //fields
    //constructors
    //methods
}

public class CALLER{

    public A getA(enum E){
        return Factory.getB(otherobject,E);
    }
}

public class Factory{
    public static B getB(object o,enum e){
         //do something with enums and get B
         b = new B();
         //populate b
         return b;
    }
}

Class B does not override any method of class A. Somehow at compile time this doesn't get any error but at runtime class CALLER excepts: java.lang.NoSuchMethodError: Factory.getB(object,enum) A

My question is: if B extends A why a method from a different class can't return A even if its return clause returns a B object directly? In fact changing:

public static B getB(object, enum);

with

public static A getB(object, enum);

solves the exception but then I get another exception (classCast) because obviously in other parts of the code it is awaiting a B type object, not an A.

Thanks in advance.

+2  A: 

You would get this exception if you had compiled CALLER.java with another version of Factory.java that would have getB returning A, then updated Factory.java so that getB returns B, then recompiled Factory.java but not CALLER.java

UPDATE:

Perhaps you want to do something like this:

public abstract class Factory {
    public abstract A getInstance(object o, enum e);
}

public class FactoryB extends Factory {
    @Override
    public B getInstance(object o,enum e){
         //do something with enums and get B
         b = new B();
         //populate b
         return b;
    }
}

But the factory would then need to be instanciated.

Maurice Perry
That's exactly what I did... why then does it gets this error? CALLER.java calls a method which never changed its signature... I mean that now B extends A so?
Lex
The method did change its signature, according to you -- its return type has changed. Just recompile everything -- in general you should not mix old and new .class files for reasons like this.
Sean Owen
@Lex - if you change a class, you need to recompile it together with any other class that depends on it.
Stephen C
@Lex: because CALLER expects Factory.getB() to return an A and not a B. A static method cannot be overridden. Perhaps you want to declare an abstract factory class (or interface), then provide subclasses of it for each A class.
Maurice Perry
Thankyou, I accept the answer, Problem SOLVED!
Lex
A: 

The first one looks like a reflection error. The java reflection classes look for the exact method signature "A getB(Object,Enum)" and not "B getB(Object,Enum)".
The second, as long as you actually create an object of type B in your getB(..) method, it will return this object. The classCast exception will only be thrown if you create a new A instead of a new B.

josefx