Cast an object to class type passed as parameter

21,025

Solution 1

If you add a constraint to child, you don't need a cast at all to get a Parent:

Parent func(Class<? extends Parent> child, String whichChild) throws Exception {
    // whichChild: "ChildA" or "ChildB"

    Parent obj = child.newInstance();
    //...
}

However, you still can't call the testChildA etc method, since all you have is an instance of Parent. You'd need to use reflection to get the method:

Method method = obj.getClass().getMethod().getMethod("test" + whichChild);
method.invoke(obj);

It would be better to have a method on the interface of Parent which you can invoke, and is overridden in the subclasses.

public abstract class Parent {
  public void test() {
    System.out.println("Test from parent");
  }

  public abstract void testChild();
}

then simply call:

obj.testChild();

or, as Emanuele Ivaldi points out, just override test in ChildA and ChildB and invoke that directly.

Solution 2

Not sure exactly what you're doing but you can use Class.cast(...).

Eg

public <T> T getInstance(Class<T> type) {
    Object o = type.newInstance();
    T t = type.cast(o);
    return t;
}
Share:
21,025
hakuna matata
Author by

hakuna matata

Updated on July 09, 2022

Comments

  • hakuna matata
    hakuna matata almost 2 years

    I have a parent class and 2 child classes. I am trying to implement a function that takes the type of the child and which child as parameters.

    When I use child.newInstance(), I want to store it in a variable of the type that is passed and call a function from the second parameter.

    Below are the classes

    public class Parent {
        public void test() {
            System.out.println("Test from parent");
        }
    }
    
    public class ChildA extends Parent {
        public void testChildA() {
            System.out.println("Test from child a");
        }
    }
    
    public class ChildB extends Parent {
        public void testChildB() {
            System.out.println("Test from child b");
        }
    }
    

    and here is the method I'm trying to implement

    public class Driver {
        Parent func(Class child, String whichChild) throws Exception {
            // whichChild: "ChildA" or "ChildB"
    
            Object obj = child.newInstance();
            // cast obj to type of child and call the method "test" and "test" + whichChild
        }
    }
    

    Can it be done what I am trying to do? If yes, how can I cast this object to the type that is passed?

  • hakuna matata
    hakuna matata over 8 years
    With reflection I can call the method testChildA even if obj is Parent in Parent obj = child.newInstance();?
  • Andy Turner
    Andy Turner over 8 years
    Sure - you can call it - but it doesn't mean that it is guaranteed to work. Method is decoupled from the instance that invoke it on. For instance, you could call method.invoke("string") - which will result in a runtime exception. It's up to you to ensure that you only call it in a way that makes sense.
  • Andy Turner
    Andy Turner over 8 years
    Why bother passing child as a parameter then? It helps if you highlight what you have actually changed, rather than just saying "try this block of code without explanation".
  • Andy Turner
    Andy Turner over 8 years
    Class<? extends Parent> constraints it.
  • Andy Turner
    Andy Turner over 8 years
    return type.newInstance() would be simpler.
  • Discern
    Discern over 8 years
    I agree with that sir. Will edit my answer, thanks :)
  • Emanuele Ivaldi
    Emanuele Ivaldi over 8 years
    The alternative would be to check the class of the object and cast it to the correct implementation and call the proper method, it's not flexible,it sucks but it avoids using reflection, did I say it sucks?
  • lance-java
    lance-java almost 7 years
    Agreed, Im just trying to show the usage of Class.cast(Object)