Runtime Java Class extension not working - java

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.

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.

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.

Related

Calling the constructor of an abstract class

Say I have the following class structure:
public class A{
A(int a){
...
}
}
abstract class B extends A{
}
public class C extends B{
C(int a){
super(a);
}
}
This code isn't valid in the sense that myMethod will not call A's constructor. Is there a way to do this?
What I ultimately want to do, is add functionality to a set of classes without affecting their functionality. All these classes currently extend a common class (runtimeException), so I was thinking of adding an intermediary abstract class.
(edit: the code in C shouldn't be a method, it was meant to be a constructor)
You will not be able to declare class B like you wrote. To create an instance of B you'll need to call A constructor:
public abstract class B extends A {
public B() {
super(10); //or other number
}
}
public class C extends B {
public C(int a) {
super();
}
}
In other words, you always call constructor of "previous level", whether the class is abstract or not.
In order to avoid this strange number 10 I wrote and missing int parameter of C constructor, I suggest adding to child class constructor at least all parameters parent class constructor requires for any extends pair of classes.
What I've seen commonly is a pattern like this:
public class A{
A(int a){
...
}
}
abstract class B extends A{
B(int a) {// "proxy" constructor"
super(a);
}
}
public class C extends B{
C(int a) {
super(a);
}
void myMethod(int a){
// super(a); <- note this is invalid code, you can only call this from the constructor
new C(0); // <-- this is valid
}
}
Granted, it's a bit verbose and boilerplate-y, but it allows you to avoid duplicating any functionality

Parent NoArgument Contructor invoking overridden method

ot sure if a similar question do exists or have been answered earlier. I did a search but couldn't find anything related.
Please see following example. There's a class A with noargument contructor. Class B extends Class A but no default contructor exists. The output is B-> get c, and I think java uses the runtime polymorphism logic to invoke the B object method.
Here would like to understand if its correct and how Java works here (Maybe what's the underlying logic)
Thanks
public class A {
private String cStr="";
private String dStr="";
A()
{
getcStr();
}
public String getcStr() {
System.out.println("A-> get c");
return cStr;
}
public String getdStr() {
System.out.println("A-> get d");
getcStr();
return dStr;
}
}
public class B extends A{
private String cStr;
public String getcStr() {
System.out.println("B-> get c");
return cStr;
}
}
public static void main (String[] args)
{
A a= new B();
a.getdStr();
}
EDIT: the output for the a.getdStr() is A-> get d B-> get c
If a class doesn't have a default constructor, in your case B, then java will implicitly insert a no argument constructor something like this
public B() {
super();
}
To answer your question, Yes, due to run time polymorphism, Java invoke's B's getcStr() method. Because B's constructor is calling A's constructor via super()
This is a famous anti-pattern. And its anti-pattern because you are trying to invoke a overriden method on B before B is fully constructed
Imagine your B class was like this
public class B extends A{
private String cStr = "abc";
public String getcStr() {
System.out.println(cStr);
return cStr;
}
}
Now the output of your program would have been null instead of "abc" because B is not fully constructed yet (that means cStr is not initialized to "abc")
there is no default constructor for B so it'll call A() constructor.....
Now new B(); creates the object of B so java will first look into class B that is any procedure like getcstr() exists if procedure found there it will invoke it otherwise check in the super class for that procedure......

Getting declaring class in Java

Having something like in Java:
class A {}
class B {private A a;}
class C {private A a;}
How could I know which is the class that declared a ?
I.e. I want to get class B or class C
Any ideas are appreciated.
Regards
You couldn't just with the structure you've specified. You'd have to pass a reference to an instance of B or C into A's constructor, then write some logic to determine the type passed in.
class A {
public void print(){
String className = new Exception().getStackTrace()[1].getClassName();
System.out.println(className);
}
}
class A1 {
private A a;
public A1(){
a= new A();
a.print();
}
}
class A2 {
private A a;
public A2(){
a= new A();
a.print();
}
}
public class C {
public static void main(String[] args) {
A1 a1= new A1();
A2 a2 = new A2();
}
}
You have to do someting like:
class A {
boolean itWasC;
public A( C objectC ) {
itWasC = true;
}
public A( B objectB ) {
itWasC = false;
}
}
And once you create an object of class "A" from class B or class C pass this to the constructor. For example: A objectA = new A( this )
It is weird, and you can't do it without instanciating objects.
As i understand the question you need to find all usages of class A (type usages) in your code (Please correct me if i'm wrong).
It depend on your IDE and the installed plugins for code inspection, most IDE's provide such a functionality, in Eclipse for example you can right click a Class and select "References->Project"
And if your IDE does not have this there are alot of tools for java, take a look at: A tool like ReSharper, but for Java?
you cannot do that in java unless you have a reference of the Object in Class A... definitely not through programatically nor in runtime.
But if you just want to find out the classes that are referencing Class A , one option is to rename the class to something else and try to compile.
And Voila , compiler would list all the classes that Reference Class A , but cannot resolve to a type.
Another alternative ,would be to use Reflections to find out the Variables in a Class and compare if the type of the variable is of Class A type
Heres a sample Program i wrote to do just that
import java.lang.reflect.Field;
import com.test.ClassA;
package com.test;
public class ClassA {
}
public class ClassB {
private ClassA classA;
public static void main(String[] args) throws Exception,
NoSuchFieldException {
Field classVariable = ClassB.class
.getDeclaredField("classA");
classVariable.setAccessible(true);
System.out.println(classVariable.getType());
System.out.println(ClassA.class);
if (ClassA.class.equals(classVariable.getType())) {
System.out.println("Class A is referenced");
}
}
}
Result
class com.test.ClassA
class com.test.ClassA
Class A is referenced

isAssignableFrom doesn't return true for sub-class

So I want to check to see if a class is assignable to a super class that contains many sub classes, something like this
public class A {
public A(){ }
}
public class B extends A {
public B(){ }
}
public class C extends B {
public C(){ }
}
public static void main() {
A a = new C();
boolean whyAmIFalse = a.getClass().isAssignableFrom(B.class);
}
Why does this return false? Obviously it can be assigned to class B as
B b = (B)a
does not return an error, so why is this returning false. Is it not the function it describes itself as? Is there a function that does accomplish what I want it to me (ie I am that class or a subclass of it)?
If what you want to do is test whether or not a's actual type is B or a subtype, you've got it backwards: it's
B.class.isAssignableFrom(a.getClass());
This is because getClass() returns the actual class, not the declared class of a variable -- a.getClass() will return the class C (C.class), which is the actual class of the object that was assigned to the variable A a and you indeed can't assign a B to a C
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#getClass()
Because class B doesn't extend/implement class C, which is what isAssignableFrom() tests. An instance of class B might be an instance of class C, as per your example. To test that, use 'instanceof'.

related to abstract class reference holding object of its derived class

class A is abstract and class B extends class A
now class A reference can hold object of class B,that is
A aObj = new B();
and assume class B has some extra methods....
like
class A
{
public show();
}
class B extends A
{
public show(){}
public method1(){}
private method2(){}
}
now tell me what things variable aObj can access from class B
can it access everything?
aObj only sees the public show() method. If you cast aObj to B, you can then access public method1(). public method2() is only accessible to the implementation of B.
For reference and completeness, here's a list of the possibilities:
A aObj = new B();
aObj.show(); // Works
aObj.method1(); // Error
aObj.method2(); // Error
And with casting to B:
B bObj = (B)aObj; bObj
bObj.show(); // Works
bObj.method1(); // Works
bObj.method2(); // Works inside bObj, but error otherwise
aObj can only use show() as the compiler thinks aObj is of type A, and the only known method of A is show().
If you know that you actually have a B you can cast that object to a B:
if (aObj instanceof B.class) {
B bObj = (B) aObj;
bObj.method1(); //OK
} else {
log.debug("This is an A, but not a B");
}
aObj.show();

Categories