简体   繁体   中英

Determine translated type for generics at runtime

My question is exactly similar to the one here . Just that, I want to do it in Java.

Suppose, I want to crate a list as:

List<a_type> myList = new ArrayList<a_type>();

The problem is that what a_type would be, is decided on the base of a condition. The two possible types are totally unrelated, having no superclass but Object in common. My problem will be solved if I can store the Type in a variable requiredType and use it as List<requiredType> . I am not sure if I'm just being greedy or foolish or ignorant in wanting this, but that's the situation.

Although not important, but the scenario that explains why I need it is explained here .


PS: Please do not mention type-erasure. Kindly consider the situation as it is. I could have very well myself mentioned it in the question. If you think there are design issues, kindly read the situation here and suggest alternatives.

That's not possible in Java, because of the type-erasure and due to the fact that generics is only limited to compiletime.

eg

List<Integer> integers = new ArrayList<Integer>();

During compiletime, when the the type-erasing is done becomes

List integers = new ArrayList();

The generics is only a way to tell the compiler, that the list should only deal with objects of type Integer , and let's it point it out if you have somewhere tried to add something other than Integer for type safety.

The only effective (if “risky”) way I could see to do so, would be something akin to:

     List<?> myList = new ArrayList<?> ();

     /* … */

     final Object o = myList.get (0);

     if (o instanceof OneType) {
           OneType o1 = (OneType)o;
           /* … */
     } else if (o instanceof OtherType) {
           OtherType o2 = (OtherType)o;
           /* … */
     } else {
           throw new RuntimeException ("unexpected type found in list…");
     }

You will probably want to litter that code with @SuppressWarnings

Possibly a better(?) idea would be to implement at least a “marker interface” (without perhaps any methods) in both types, and use that as the commonality.

     public interface CanBeAddedToDualTypedList { };
     public class OneType implements CanBeAddedToDualTypeList { … };
     public class OtherType implements CanBeAddedToDualTypeList { … };


     List<CanBeAddedToDualTypedList> myList = 
                     new ArrayList<CanBeAddedToDualTypedList> ()

Edit I also put an answer on your related question, showing a concrete example of using a common interface for that specific case.

Java generic are not available at runtime so not possible with java

Search for "Type Erasure" on google and you will understand it better.

You can store the a_type.class object while that wont help you with generics, it can be used to add additional runtime type checks class.cast(...) .

Generics do not support runtime typing, the generic type itself does not exist at runtime. C# has a runtime class for each Generic type List<String> is different from List<int> . In java this is not the case both List<String> and List<Integer> degrade to List at runtime.

AFAIK (never tried it) extending a Generic class stores the type somewhere accessible to reflection class StringList extends List<String>{} , the StringList remembers the Generic type used to extend List.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM