So basically I have List with some container, that contain generic object:
List<MyObj<?>> myObjList;
For example there can be MyObj<A> and MyObj<B>. And there some overloaded method todo(A a) and todo(B b).
If i wanna call this method in cycle, I need hardcode casting to A or B:
for(MyObj<?> myObj: myObjList) {
todo( (A) myObj.body() )
}
Is there a way to casting using class literal A.class?
I'm tried add class literal field to myObj:
class myObj<T> {
Class<T> classLiteral;
T body;
}
and use .cast() method:
for(MyObj<?> myObj: myObjList) {
todo(
myObj.getClassLiteral().cast( myObj.body() )
)
}
But it didn't work
Related
In a Java application I'm working on, I have a number of enums which ended up having a static fromString method in them for converting a string to its actual enum value.
So, I thought I could have a "base" class from which all my enums can extend without have to repeat that code all the time. Since enums cannot extend classes, I've planned to do is that I might be able to do that through an interface instead.
What I've is the following:
public interface IBaseEnum {
String enumVal = null;
public static <T extends Enum<T> & IBaseEnum> Enum<T> fromString(String strVal) {
if (strVal == null) return null;
// T.values() has error because T is not recognised to have the method values()
for (T myEnum : T.values()) {
if (myEnum.enumVal.equals(strVal.toUpperCase())) {
return myEnum;
}
}
return null;
}
}
And then, to inherit that static method, I will implement IBaseEnum in my actual Enum:
public enum Colour implements IBaseEnum {
Red("red");
//...
}
However, I'm having issues with the types in IBaseEnum. The line T.values() is having error because the generic type T cannot be referenced back to the enum itself and so it is complaining that the method values() is not found.
Is this the right way to inherit functionalities in enum? Otherwise, how can I inherit methods in enums so that I don't have to copy/paste and repeat a same set of methods in every single enums?
There are a few reasons why your code would not work, of which I should mention:
String enumVal = null;: IBaseEnum being an interface, numVal gets the implicit public, static, and final modifiers. However, you intend enumVal to be an instance property.
T.values(): of course this doesn't compile. But even if it could (or you had the class instance), you still wouldn't be able to make this dynamic. Static methods are picked at compile time. The only way (that I know) to make it work dynamically would be to use reflection, of course passing in the class object of the enum.
Because you want to be able to call Color.fromString(...), you have no choice but to declare this as a static method in each enum class. With that said, I think the most you can reuse from your logic is the lookup code (again, that's unless you use reflection).
To reuse the lookup logic, you can change the contract of IBaseEnum to make it declare a method that that returns the enumVal value. Beside that, the values() method can be invoked by the enum classes themselves. Here's what it can look like:
interface IBaseEnum {
String enumVal();
public static <T extends Enum<T> & IBaseEnum> T
fromString(String strVal, T[] values) {
if (strVal == null)
return null;
for (T myEnum : values) {
if (myEnum.enumVal().equalsIgnoreCase(strVal)) {
return myEnum;
}
}
return null;
}
}
And that will lead to an enum class like the following:
enum Colour implements IBaseEnum {
VAL1("string")
;
private final String val;
Colour(String v) {
this.val = v;
}
#Override
public String enumVal() {
return this.val;
}
public static Colour fromString(String s) {
return IBaseEnum.fromString(s, values());
}
}
Remember: if enumVal() is intended to return just the enum literal, then you can get rid of all this complexity by just using the valueOf method available in all enums. Only do this if the comparison of your values needs custom logic.
This question already has answers here:
Reflection for Class of generic parameter in Java?
(6 answers)
Closed 4 years ago.
Following Example:
I have a service that can 'start' any vehicle
interface VehicleStarterService<T: Vehicle> {
fun <T : Vehicle> start(vehicle: Class<T>): String {
return vehicle.start
}
}
I would like to start a vehicle type by name like "Car", which would require me to create a VehicleStarterService; however I cannot seem to find a way to instantiate an interface with a class that is instantiated by name.
I would like to do something like (but cannot):
val cls = "Car"
val kClass = Class.forName(cls).kotlin
val service = VehicleStarterService<kClass>()
service.start
I end up having to do the following (creating a service for every paramaterized type I need):
class CarStarterService : VehicleStarterService<Car> {
fun <T> execute() : String {
return start(User::class.java)
}
}
Is there any way to instantiate a paramaterized class in this way?
It's not clear if this would be sufficient for your situation, but perhaps you could just match the class based on the string like this
val cls = "Car"
val service: VehicleStarterService<out Vehicle>? = when (cls) {
"Car" -> object : VehicleStarterService<Car> {}
"Boat" -> object : VehicleStarterService<Boat> {}
"Plane" -> object : VehicleStarterService<Plane> {}
else -> null
}
service?.start(...
EDIT: hashmap registry idea to allow some extensibility..
val serviceRegistry = HashMap<String, VehicleStarterService<out Vehicle>>()
.apply {
//default services
this["Car"] = object : VehicleStarterService<Car> {}
this["Boat"] = object: VehicleStarterService<Boat> {}
}
.
.
.
//Adding entry
serviceRegistry["Plane"] = object: VehicleStarterService<Plane> {}
.
.
.
//Fetching entry
val cls = "Car"
val service = serviceRegistry[cls]
service?.start(...
I don't really see your problem. Note that the generic type information is erased at runtime (at least for the JVM-variant which you are obviously using). So it basically doesn't matter which generically typed service you use.
You can also just use VehicleStarterService<Vehicle> and it will start all your vehicles. If for any reason you need to call a specific (other!) function you still need to check/cast to your actual type... So I see no benefit in trying to get that generic typed interface.
Having said that there are still methods to do it... (note again: it doesn't really matter... generic type information is erased at runtime...)
Now for my tests I use this entry method:
fun startAllTheVehicles(vararg vehicleTypes: String) {
startAllTheVehicles(*vehicleTypes.map { Class.forName(it) }
.map { it as Class<out Vehicle> }
.toTypedArray())
}
Note that it as Class<out Vehicle> is NOT ensuring that you have a class of type Vehicle. It just makes sure that your code compiles when trying to call your functions that declare Class<out Vehicle> as a parameter type.
So starting from there you could use one of the following ways to have an actual generic type available. I am assuming you use something like newInstance within your start service.
Sample with the generic type omitted on the interface (that case is rather easy):
interface VehicleStarterService {
fun <T: Vehicle> start(vehicleType: Class<T>) = vehicleType.newInstance().start
}
Sample method that is called by the above entry function using one service to start all vehicles:
fun <T : Vehicle> startAllTheVehicles(vararg vehicleTypes: Class<out T>) {
val service = object : VehicleStarterService {}
vehicleTypes.forEach { service.start(it) }
}
Still using an interface with generic type (note the changes regarding out T, etc.):
interface VehicleStarterService<T: Vehicle> {
fun start(vehicleType: Class<out T>) = vehicleType.newInstance().start
}
Sample method that is called by the entry function using one service to start all vehicles:
fun <T : Vehicle> startAllTheVehicles(vararg vehicleTypes: Class<out T>) {
// actually it doesn't really matter which type we use...
val service = object : VehicleStarterService<Vehicle> {} // you could even use T instead of Vehicle
vehicleTypes.forEach { service.start(it) }
}
Testing both with the following works as expected:
startAllTheVehicles("Car", "Truck")
Calling it with a type that is actually no Vehicle will give you a ClassCastException at the interface's start-function.
I have a Java enum with an abstract class, like this:
public enum Strategy {
STRING {
#Override
public String execute() {
return "ABCDE";
}
},
INTEGER {
#Override
public Integer execute() {
return 12345;
}
};
public abstract Object execute();
}
When I use it, I expect to be able to do this:
String text = Strategy.STRING.execute();
Integer num = Strategy.INTEGER.execute();
However, my IDE warns me that these are incompatible types and won't compile. To resolve it, I have to instead do this:
String text = (String) Strategy.STRING.execute();
Integer num = (Integer) Strategy.INTEGER.execute();
I'd rather not have to cast the results of my execute() methods. Is there any way to return the type specified in the concrete method signature, rather than returning Object?
When you override a method, the subclass method can be declared to return a refinement of the superclass return type. However, code that calls the superclass method has no way of knowing what the actual type is of the returned object. In your case, all it knows is that it's an Object of some sort. That's why you have to cast it before assigning to a more specific variable.
Enum objects are a little weird. When you compile this code:
Strategy.STRING.execute();
the compiler generates this bytecode (output from javap -c):
getstatic #2 // Field Strategy.STRING:LStrategy;
invokevirtual #3 // Method Strategy.execute:()Ljava/lang/Object;
As you can see, it treats Strategy.STRING as a static field of class Strategy, and that field is of type Strategy. Thus, despite appearances, the calling code doesn't know that it's calling the STRING version of execute().
I wonder, though, why you would want to do all this. Designing an API that requires a cast seems contrary to the spirit of object-oriented programming.
Your enum constants are compiled to static fields. Something like
public static final Strategy INTEGER = new Strategy() {
#Override
public Integer execute() {
return 12345;
}
};
Because they are simply Strategy references, you only have access to the Strategy 'interface' which declares the execute() method as returning an Object.
So, no, you won't be able to get it to do
Integer num = Strategy.INTEGER.execute();
in this way.
Given the following interface:
public interface GenericInterface<T> {
T getValue();
void setValue(T newVal);
}
And the following impl:
public class FixedImpl implements GenericInterface<String> {
String value;
public FixedImpl(String value) {
this.value = value;
}
#Override
public String getValue() {
return value;
}
#Override
public void setValue(String newVal) {
value = newVal;
}
}
I want to be able to determine that in the case of FixedImpl, String.class is the value for GenericInterface.T by interrogating FixedImpl.class.
My current idea:
Find a method name in GenericInterface that returns a <T> - in this case, there's "getValue".
Go through all the methods declared in FixedImpl.class with the same name, and collect all the different return types.
The return type farthest from Object is my value for GenericInterface.T.
But there's a couple of issues with this process:
It will only work for generic types containing a method that returns <T>. You can't safely do the same trick using setValue(T), because method overloading by parameter / arity is possible to do in Java source. It only works for T getValue() because overloading by return value isn't (unless I'm mistaken).
It might have weird interactions with Java 8 default methods, or a generic method implementation in a (still generic) possibly abstract superclass.
It's kinda kludgey.
Can anybody point me to an easier / more surefire way to get the same information? I can't seem to find one, but I thought I'd ask the superior intellects of the toobs :)
NB: If you're wondering why I'd need this, it's because I want to programatically construct mocks of container classes with similar hard-coded type parameters, but POJO values rather than simple Strings.
EDIT: I eventually worked out the following solution (before seeing #stony-zhang's):
public static <G> List<Class> getConcreteTypes(Class<? extends G> implClass, Class<G> genericClass) {
List<Class> concreteTypes = new ArrayList<Class>();
for (Type type : implClass.getGenericInterfaces()) {
if (!(type instanceof ParameterizedTypeImpl)) continue;
ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) type;
if (parameterizedType.getRawType() != genericClass) continue;
for (Object arg : parameterizedType.getActualTypeArguments()) {
if (!(arg instanceof Class))
throw new IllegalArgumentException("Class " + implClass + " not concrete for generic type " + genericClass);
concreteTypes.add((Class) arg);
}
}
return concreteTypes;
}
You can get the the class of T by the following way, in the interface add a method getMessageClass(), and in the FixedImpl add the implemented method,
#SuppressWarnings("rawtypes")
public Class getMessageClass() {
int index =0; //In the case, you only have a generic type, so index is 0 to get the first one.
Type genType = getClass().getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
throw new RuntimeException("Index outof bounds");
}
if (!(params[index] instanceof Class)) {
return Object.class;
}
return (Class) params[index];
}
In you case, if you have multiple subclass, to use it, create one abstract class to implement the interface GenericInterface, and then the all subclass extends from the new abstract class,
public class abstract abstractImpl<T> implements implements GenericInterface<T> {
#SuppressWarnings("rawtypes")
#Override
public Class getMessageClass() {
...............
}
}
Remember type erasure. At runtime, there is no type information about your generics anymore, unless you specify it yourself. And this is what you should do. Add this to your interface:
Class<T> getTypeOfT();
And add this to your FixedImpl:
#Override
public Class<String> getTypeOfT()
{
return String.class;
}
That way, you can always call getTypeOfT() on your GenericInterface<T> implementations and find out what type you are dealing with.
I don't think that you will be able to get reliable result because of Type Erasure:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety.
Generate bridge methods to preserve polymorphism in extended generic types.
Your approach of of using the types of objects returned may at first seem alright, but beyond the issues you have pointed out there is no way (at runtime) to know if The return type farthest from Object is my value for GenericInterface.T.
My suggestion would be to use some kind of configuration XML which could be generated at build time based on the java source (using a build tool such as Ant), which would in turn be used to create Mock objects, or you could simply generate the tests based off the source at buildtime.
If you don't mind changing your runtime code for the purposes of testing, Jan Doereenhaus' answer suggests a simple hard-coded mechanism for retrieving the type
EDIT:
Consider the scenario:
public class FixedImpl implements GenericInterface<SomeClass> {
#Override
public SomeClass getValue() {
return new SomeClass();
}
}
public class FixedImpl2 extends FixedImpl {
#Override
public SomeClass getValue()
{
return new SomeSubClass();
}
}
From this example, you can see that the sub class of FixedImpl is able to return a subclass of T (which is further down the inheritance hierarchy from Object)
I would like to create an object of Generics Type in java. Please suggest how can I achieve the same.
Note: This may seem a trivial Generics Problem. But I bet.. it isn't. :)
suppose I have the class declaration as:
public class Abc<T> {
public T getInstanceOfT() {
// I want to create an instance of T and return the same.
}
}
public class Abc<T> {
public T getInstanceOfT(Class<T> aClass) {
return aClass.newInstance();
}
}
You'll have to add exception handling.
You have to pass the actual type at runtime, since it is not part of the byte code after compilation, so there is no way to know it without explicitly providing it.
In the code you posted, it's impossible to create an instance of T since you don't know what type that is:
public class Abc<T>
{
public T getInstanceOfT()
{
// There is no way to create an instance of T here
// since we don't know its type
}
}
Of course it is possible if you have a reference to Class<T> and T has a default constructor, just call newInstance() on the Class object.
If you subclass Abc<T> you can even work around the type erasure problem and won't have to pass any Class<T> references around:
import java.lang.reflect.ParameterizedType;
public class Abc<T>
{
T getInstanceOfT()
{
ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
Class<T> type = (Class<T>) superClass.getActualTypeArguments()[0];
try
{
return type.newInstance();
}
catch (Exception e)
{
// Oops, no default constructor
throw new RuntimeException(e);
}
}
public static void main(String[] args)
{
String instance = new SubClass().getInstanceOfT();
System.out.println(instance.getClass());
}
}
class SubClass
extends Abc<String>
{
}
What you wrote doesn't make any sense, generics in Java are meant to add the functionality of parametric polymorphism to objects.
What does it mean? It means that you want to keep some type variables of your classes undecided, to be able to use your classes with many different types.
But your type variable T is an attribute that is resolved at run-time, the Java compiler will compile your class proving type safety without trying to know what kind of object is T so it's impossible for it to let your use a type variable in a static method. The type is associated to a run-time instance of the object while public void static main(..) is associated to the class definition and at that scope T doesn't mean anything.
If you want to use a type variable inside a static method you have to declare the method as generic (this because, as explained type variables of a template class are related to its run-time instance), not the class:
class SandBox
{
public static <T> void myMethod()
{
T foobar;
}
}
this works, but of course not with main method since there's no way to call it in a generic way.
EDIT: The problem is that because of type erasure just one generic class is compiled and passed to JVM. Type checker just checks if code is safe, then since it proved it every kind of generic information is discarded.
To instantiate T you need to know the type of T, but it can be many types at the same time, so one solution with requires just the minimum amount of reflection is to use Class<T> to instantiate new objects:
public class SandBox<T>
{
Class<T> reference;
SandBox(Class<T> classRef)
{
reference = classRef;
}
public T getNewInstance()
{
try
{
return reference.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
SandBox<String> t = new SandBox<String>(String.class);
System.out.println(t.getNewInstance().getClass().getName());
}
}
Of course this implies that the type you want to instantiate:
is not a primitive type
it has a default constructor
To operate with different kind of constructors you have to dig deeper into reflection.
You need to get the type information statically. Try this:
public class Abc<T> {
private Class<T> clazz;
public Abc(Class<T> clazz) {
this.clazz = clazz;
}
public T getInstanceOfT()
throws throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException,
NoSuchMethodException,
SecurityException {
return clazz.getDeclaredConstructor().newInstance();
}
}
Use it as such:
Abc<String> abc = new Abc<String>(String.class);
abc.getInstanceOfT();
Depending on your needs, you may want to use Class<? extends T> instead.
The only way to get it to work is to use Reified Generics. And this is not supported in Java (yet? it was planned for Java 7, but has been postponed). In C# for example it is supported assuming that T has a default constructor. You can even get the runtime type by typeof(T) and get the constructors by Type.GetConstructor(). I don't do C# so the syntax may be invalid, but it roughly look like this:
public class Foo<T> where T:new() {
public void foo() {
T t = new T();
}
}
The best "workaround" for this in Java is to pass a Class<T> as method argument instead as several answers already pointed out.
First of all, you can't access the type parameter T in the static main method, only on non-static class members (in this case).
Second, you can't instantiate T because Java implements generics with Type Erasure. Almost all the generic information is erased at compile time.
Basically, you can't do this:
T member = new T();
Here's a nice tutorial on generics.
You don't seem to understand how Generics work.
You may want to look at http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html
Basically what you could do is something like
public class Abc<T>
{
T someGenericThing;
public Abc(){}
public T getSomeGenericThing()
{
return someGenericThing;
}
public static void main(String[] args)
{
// create an instance of "Abc of String"
Abc<String> stringAbc = new Abc<String>();
String test = stringAbc.getSomeGenericThing();
}
}
I was implementing the same using the following approach.
public class Abc<T>
{
T myvar;
public T getInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException
{
return clazz.newInstance();
}
}
I was trying to find a better way to achieve the same.
Isn't it possible?
Type Erasure Workaround
Inspired by #martin's answer, I wrote a helper class that allows me to workaround the type erasure problem. Using this class (and a little ugly trick) I'm able to create a new instance out of a template type:
public abstract class C_TestClass<T > {
T createTemplateInstance() {
return C_GenericsHelper.createTemplateInstance( this, 0 );
}
public static void main( String[] args ) {
ArrayList<String > list =
new C_TestClass<ArrayList<String > >(){}.createTemplateInstance();
}
}
The ugly trick here is to make the class abstract so the user of the class is forced to subtype it. Here I'm subclassing it by appending {} after the call to the constructor. This defines a new anonymous class and creates an instance of it.
Once the generic class is subtyped with concrete template types, I'm able to retrieve the template types.
public class C_GenericsHelper {
/**
* #param object instance of a class that is a subclass of a generic class
* #param index index of the generic type that should be instantiated
* #return new instance of T (created by calling the default constructor)
* #throws RuntimeException if T has no accessible default constructor
*/
#SuppressWarnings( "unchecked" )
public static <T> T createTemplateInstance( Object object, int index ) {
ParameterizedType superClass =
(ParameterizedType )object.getClass().getGenericSuperclass();
Type type = superClass.getActualTypeArguments()[ index ];
Class<T > instanceType;
if( type instanceof ParameterizedType ) {
instanceType = (Class<T > )( (ParameterizedType )type ).getRawType();
}
else {
instanceType = (Class<T > )type;
}
try {
return instanceType.newInstance();
}
catch( Exception e ) {
throw new RuntimeException( e );
}
}
}
There are hacky ways around this when you really have to do it.
Here's an example of a transform method that I find very useful; and provides one way to determine the concrete class of a generic.
This method accepts a collection of objects as input, and returns an array where each element is the result of calling a field getter on each object in the input collection. For example, say you have a List<People> and you want a String[] containing everyone's last name.
The type of the field value returned by the getter is specified by the generic E, and I need to instantiate an array of type E[] to store the return value.
The method itself is a bit ugly, but the code you write that uses it can be so much cleaner.
Note that this technique only works when somewhere in the input arguments there is an object whose type matches the return type, and you can deterministically figure it out. If the concrete classes of your input parameters (or their sub-objects) can tell you nothing about the generics, then this technique won't work.
public <E> E[] array (Collection c) {
if (c == null) return null;
if (c.isEmpty()) return (E[]) EMPTY_OBJECT_ARRAY;
final List<E> collect = (List<E>) CollectionUtils.collect(c, this);
final Class<E> elementType = (Class<E>) ReflectionUtil.getterType(c.iterator().next(), field);
return collect.toArray((E[]) Array.newInstance(elementType, collect.size()));
}
Full code is here: https://github.com/cobbzilla/cobbzilla-utils/blob/master/src/main/java/org/cobbzilla/util/collection/FieldTransformer.java#L28
It looks like you are trying to create the class that serves as the entry point to your application as a generic, and that won't work... The JVM won't know what type it is supposed to be using when it's instantiated as you start the application.
However, if this were the more general case, then something like would be what you're looking for:
public MyGeneric<MyChoiceOfType> getMeAGenericObject(){
return new MyGeneric<MyChoiceOfType>();
}
or perhaps:
MyGeneric<String> objMyObject = new MyGeneric<String>();
Abc<String> abcInstance = new Abc<String> ();
..for example