0

I have a set of classes that extend a generic class. This class in turn implements an interface. I want to be able to instantiate the objects that extent this class based on some string value, using reflection.

Interface

public interface Vehicle {
    public String reportStats();
}

Generic Class

public class Premium implements Vehicle {
    public String reportStats() {
        return "generic stats";
    }
}

One type

public class Volvo extends Premium {

    public void drive() {
         // impl
    }
}

Another type

public class Mercedez extends Premium {

    public void drive() {
         // impl
    }
}

Trying to instantiate using reflection

String objectStr = "org.test.project.impl.Volvo";
Class<? extends Vehicle> vehicleClass;
vehicleClass = (Class<? extends Vehicle>) Class.forName(objectStr);

// this does not work
// the error that i get is Volvo cannot be casted to Vehicle
Vehicle vehicle = vehicleClass.cast(vehicleClass.newInstance());
String stats = vehicle.reportStats();

This appears to be working if the classes are in the same jar, but if Mercedez or Volvo are factored out into a separate jar, under the same package, the cast fails with a java.lang.ClassCastException.

Thanks.

VilleLipponen
  • 636
  • 1
  • 13
  • 22
  • Your code seems correct. Can you post in full the exact exception you get? – Nikem Jan 26 '19 at 10:01
  • 2
    Your code seems to be working fine for me: https://ideone.com/0F5iZs (I needed to change `(Class extends Vehicle>) Class.forName(objectStr)` to `Volvo.class` but that shouldn't cause any difference). Please take your time and make sure that your [mcve] really reproduces your problem. – Pshemo Jan 26 '19 at 10:08
  • 2
    By the way, instead of the unchecked cast, you can use `Class.forName(objectStr).asSubclass(Vehicle.class)`. You also don't need to use `vehicleClass.cast(...)`, because `vehicleClass.newInstance()` will already return `Vehicle`. https://ideone.com/RXuZEq – Radiodef Jan 26 '19 at 10:15
  • @Pshemo, changing it to Volvo.class does in fact cause the problem - we don't know at compile time what string will be passed to the method that instantiates an Object. It could be "Volvo". It could be "Wabalabadubdub" . The class is determined at runtime. – VilleLipponen Jan 26 '19 at 14:51
  • Code worked fine for me. I just had to add a couple of exceptions to catch. – sbstnzmr Jan 26 '19 at 16:38
  • To let that code run on online IDE I linked earlier I had to use `Volvo.class` instead of `Class.forName` since that IDE doesn't allow us to create packages. I didn't mean that these are *same* things, but that in context of your example they should give same results (assuming `String objectStr = "org.test.project.impl.Volvo";`). – Pshemo Jan 27 '19 at 02:58

0 Answers0