How to assign a generic enum in a constructor in java? - java

I have the following code
import java.util.Arrays;
public class CustomEnum {
//?? varName;
public <E extends Enum<E>> CustomEnum(Class<E> enumClass) {
System.out.println(Arrays.toString(enumClass.getEnumConstants()));
//?? varName = enumClass;
}
}
public enum Mode {
SAMPLE_A,
SAMPLE_B,
SAMPLE_C,
SAMPLE_D
}
and I can call it in this way
public static void main(String[] args) {
CustomEnum customEnum = new CustomEnum(Mode.class);
}
code output
[SAMPLE_A, SAMPLE_B, SAMPLE_C, SAMPLE_D]
What I want to do is assign the value of enumClass to a variable and assign it in the constructor but I don't know which type the variable should be, I tried with multiple ways but I get compilation errors, is this possible?
if the above is not possible, how could I convert a generic type
E[] which is returned by getEnumConstants() to a String[]?

Make the whole class generic, not just the constructor.
public class CustomEnum<E extends Enum<E>> {
private E[] constants;
public CustomEnum(Class<E> enumClass) {
constants = enumClass.getEnumConstants();
}
}

Related

How to get a class instance of type Foo<T> (Foo<T>.class not work) [duplicate]

This question already has answers here:
Java: how do I get a class literal from a generic type?
(8 answers)
Closed 4 years ago.
I would like to get the class of Foo< T >.class (exactly Foo < T>, neither T.class nor Foo.class)
public class A extends B<C<D>>{
public A() {
super(C<D>.class); // not work
}
}
On StackOverflow has a instruction for obtaining generic class by injecting into constructor but it's not my case because C< D>.class (e.g List<
String>.class) is syntax error. At here it seems relate to syntax more than code structure.
To show more detail, higher level view, the original code is the following, its HATEOAS module in Spring framework:
public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, CustomerGroupResource>{
public CustomerGroupResourceAssembler() {
super(CustomerGroupController.class, CustomerGroupResource.class);
}
}
public class CustomerGroupResource extends ResourceSupport {
private CustomerGroup data;
}
But now I want to parameterize the CustomerGroupResource to
public class Resource<T> extends ResourceSupport {
private T data;
}
and then
public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, Resource<CustomerGroup>>{
public CustomerGroupResourceAssembler() {
super(CustomerGroupController.class, Resource<CustomerGroup>.class); // not work here, even Resource.class
}
}
Unfortunately what you are trying to do is impossible due to type erasure.
Information about generic types is only avalilable at compile time and not at run time. This is one of biggest limitations of using generics in Java. The reason why it was done like this is to preserve backwards compatibility.
See Java generics type erasure: when and what happens?
Due to type erasure, the generic only applies at compile time and doesn't mean anything at runtime. What you can do is
public class A extends B<C<D>>{
public A() {
super((Class<C<D>>) C.class);
}
}
However, you won't be able to determine the type of D at runtime. You can use reflection to get the super type however.
public class Main {
public static abstract class B<X> {
protected B() {
Type type = getClass().getGenericSuperclass();
System.out.println(type);
}
}
public static class A extends B<Supplier<String>> {
public A() {
}
}
public static void main(String[] args) {
new A();
}
}
prints
Main.Main$B<java.util.function.Supplier<java.lang.String>>
EDIT For your specific example you can do.
import java.lang.reflect.Type;
public interface Main {
class ResourceSupport {
}
class CustomerGroup {
}
public class Resource<T> extends ResourceSupport {
private T data;
}
abstract class ResourceAssemblerSupport<C, R> {
protected ResourceAssemblerSupport() {
Type type = getClass().getGenericSuperclass();
System.out.println(type);
ParameterizedType pt = (ParameterizedType) type;
Type[] actualTypeArguments = pt.getActualTypeArguments();
Class first = (Class) actualTypeArguments[0];
ParameterizedType second = (ParameterizedType) actualTypeArguments[1];
System.out.println(pt.getRawType() + " <" + first + ", " + second + ">");
}
}
public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, Resource<CustomerGroup>>{
public CustomerGroupResourceAssembler() {
}
}
public static void main(String[] args) {
new CustomerGroupResourceAssembler();
}
}
prints
Main.Main$ResourceAssemblerSupport<Main$CustomerGroup, Main.Main$Resource<Main$CustomerGroup>>
class Main$ResourceAssemblerSupport <class Main$CustomerGroup, Main.Main$Resource<Main$CustomerGroup>>
A generic way to do what you want is to use a helper function, however I think this isn't needed in your case.
public static void main(String[] args) {
System.out.println(new ClassType<List<String>>() {}.getType());
}
interface ClassType<T> {
default Type getType() {
ParameterizedType type = (ParameterizedType) getClass().getGenericInterfaces()[0];
return type.getActualTypeArguments()[0];
}
}
prints
java.util.List<java.lang.String>

Create dynamic Type Java

explain my problem:
I have a super abstract class called First and then I have a lot of class that inherit from it.
I want to build a method that I "say" to it "create a ArrayList of one of the types that inherit from First class", but I'm not to able to find solution.
For example:
public abstract class First{
public First(){
}
}
public class FirstOne extends First{
...........
}
//It's a pseudo-code
public class MyProgramClass{
public creatingMethod(TypeThatInheritFromFirstClass x ){
return ArrayList<TypeThatInheritFromFirstClass>;
}
}
I insert creatingMethod in program class,but it can be anywhere(I prefer in First class like static method, but it's an example)
Thank for your time
You could use a type token:
public class SomeGenerics {
public static void main(String[] args) {
List<SubFirst1> list1 = creatingMethod(SubFirst1.class);
List<SubFirst2> list2 = creatingMethod(SubFirst2.class);
}
public static <T extends First> List<T> creatingMethod(Class<T> type) {
return new ArrayList<>();
}
}
class First {}
class SubFirst1 extends First {}
class SubFirst2 extends First {}
EDIT as per the comment:
As you already have the type token, you can use it for creating instances of that type. A little restriction is, that you must know what constructor to use. If they - for example - all have a parameterless constructor, you can create instances like that:
public static <T extends First> List<T> creatingMethod(Class<T> type) throws ReflectiveOperationException {
List<T> result = new ArrayList<>();
result.add(type.newInstance());
return result;
}
If you have a constructor with parameters (again: all sub classes must have the same parameterized constructor), you must go a more difficult way. Example with a string parameter:
public static <T extends First> List<T> creatingMethod(Class<T> type, String param) throws ReflectiveOperationException {
List<T> result = new ArrayList<>();
Constructor<T> constructor = type.getDeclaredConstructor(String.class);
result.add(constructor.newInstance(param));
return result;
}

Getting Type instance of implemented interface with type parameters applied

Given a Type instance (which may be a Class or ParameterizedType), I need to get the specific Type of an interface implemented by the class. Without generics this is easy, call getInterfaces() on a Class instance and you're done. However, I need this to work even when the implemented interface has its own type parameters that may or may not depend on the type parameters of the original class itself.
Some examples, the function should return Iterable<Integer> when given a class
class Foo implements Iterable<Integer> {}
but must also return Iterable<String> given the class
class Bar<T> implements Iterable<T> {}
and a ParmeterizedType representing Bar<String>
Is there an easy way to do this with built in reflection, third party tools etc?
To clarify, this needs to work not only with type instances retrieved via literals (Foo.class etc), but also those returned via reflection that can contain applied type parameters, for example the return type returned via reflection from the method
static Bar<String> magic() { ... }
This would be a ParameterizedType referencing the raw Bar class and the String type argument.
You should probably have a look at the Google Guava TypeToken class: http://code.google.com/p/guava-libraries/wiki/ReflectionExplained
It offers sophisticated mechanisms for resolving types in various contexts. And if I understood your question correctly, then something like the TypeToken#resolveType(Type) method might be close to what you are looking for:
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Iterator;
import com.google.common.reflect.TypeToken;
class Foo implements Iterable<Integer> {
#Override
public Iterator<Integer> iterator()
{
return null;
}
}
class Bar<T> implements Iterable<T> {
#Override
public Iterator<T> iterator()
{
return null;
}
}
public class TypeParameterTest
{
public static void main(String[] args) throws Exception
{
Type i0 = getInterface(Foo.class, 0);
System.out.println("First interface implemented by Foo: "+i0);
Method method = TypeParameterTest.class.getDeclaredMethod("magic");
Type returnType = method.getGenericReturnType();
System.out.println("Magic method return type: "+returnType);
Type i1 = getInterface(returnType, 0);
System.out.println("First interface implemented by Bar<String>: "+i1);
}
private static Type getInterface(Type type, int interfaceIndex)
{
TypeToken<?> typeToken = TypeToken.of(type);
Class<?> c = typeToken.getRawType();
Type[] interfaces = c.getGenericInterfaces();
if (interfaces.length == 0)
{
return null;
}
Type i = interfaces[interfaceIndex];
return typeToken.resolveType(i).getType();
}
public static Bar<String> magic() { return null; }
}
The output here is
First interface implemented by Foo: java.lang.Iterable<java.lang.Integer>
Magic method return type: Bar<java.lang.String>
First interface implemented by Bar<String>: java.lang.Iterable<java.lang.String>
You can use reflections when the type is hard coded because it subclasses a specific type. Here the type is stored in the class information.
If you use reflections, you can see that Foo extends Iterable<String> but if you have a Bar<String> this is just a Bar at runtime due to type erasure and all you see is that Bar extends Iterable<T>
If you have a generic type which is parameterised, this is not recorded anywhere as it has no action at runtime. If you need this type, you need save it as an additional field.
e.g. There is a class Collections.CheckedMap which checks the types at runtime and it starts like this
private static class CheckedMap<K,V>
implements Map<K,V>, Serializable
{
private static final long serialVersionUID = 5742860141034234728L;
private final Map<K, V> m;
final Class<K> keyType;
final Class<V> valueType;
Here is an example of using ParameterizedType
import java.lang.reflect.*;
public class Foo {
static class Bar<T> {
}
static class SubBar extends Bar<Integer> {
}
public static void main(String argv[]) {
ParameterizedType pt = (ParameterizedType)SubBar.class.getGenericSuperclass();
Type[] t = pt.getActualTypeArguments();
for (int i=0;i<t.length;i++) {
System.out.println(t[i]);
}
}
}
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
public class Dummy implements Iterable<Integer> {
public static void main(String args[]) throws Exception {
Dummy d = new Dummy();
Type[] genericInterfaces = Dummy.class.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
Type[] genericTypes = ((ParameterizedType) genericInterface).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("Generic type: " + genericType);
}
}
}
}
#Override
public Iterator<Integer> iterator() {
// TODO Auto-generated method stub
return null;
}
}

Get actual enum class of the Parameterized class T extends Enum<?>

I have a class:
public class MultipleSorting<T extends Enum<?>> {
private T criteriaType;
public Class<T> getCriteriaClass() {
Field field = ReflectionUtils.getField(getClass(),"criteriaType");
ReflectionUtils.makeAccessible(field);
return (Class<T>)field.getType();
}
}
This class is get instantiated as:
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?,?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController() {
super();
multipleSorting = new MultipleSorting<U>();
}
}
The actual value of U is passed from the child class of MultiSortPageableController which is:
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T,ArticleSortField> {
}
The ArticleSortField is an Enum.
I was expecting the method getCriteriaClass of MultipleSorting would return ArticleSortField from a method of MultiSortPageableController. But it is returning java.lang.Enum.
I am unable to figure it out why it is not returning the actual enum and how can I make it so. Any pointer would be very helpful to me. I need to get ArticleSortField.
Purpose:
I two requirement:
To get the actual class of enum type (say ArticleSortField.class)
To list enum value. If I have the enum class, then I could invoke class..getEnumConstants().
Java compiler removes information about generics, therefore when you use reflection you get no information about the declared type, other than Enum. This process is called type erasure.
How about passing the type down, via the constructor, like this:
public class MultipleSorting<T extends Enum<?>> {
private Class<T> criteriaType;
MultipleSorting(Class<T> criteriaType) {
this.criteriaType = criteriaType;
}
public Class<T> getCriteriaClass() {
return criteriaType;
}
}
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?, ?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController(Class<U> criteriaType) {
super();
multipleSorting = new MultipleSorting<U>(criteriaType);
}
}
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T, ArticleSortField> {
public AbstractArticleSearchController() {
super(ArticleSortField.class);
}
}

How to get the class of type variable in Java Generics

I've seen similar questions but they didnt help very much.
For instance I've got this Generic Class:
public class ContainerTest<T>
{
public void doSomething()
{
//I want here to determinate the Class of the type argument (In this case String)
}
}
and Another Class which uses this Container Class
public class TestCase
{
private ContainerTest<String> containerTest;
public void someMethod()
{
containerTest.doSomething();
}
}
Is it possible to determinate the Class of the type argument in method doSomething() without having an explicit type variable/field or any constructor in ContainerTest Class?
Update: Changed format of ContainerTest Class
The only way is to store the class in an instance variable and require it as an argument of the constructor:
public class ContainerTest<T>
{
private Class<T> tClass;
public ContainerTest(Class<T> tClass) {
this.tCLass = tClass;
}
public void doSomething()
{
//access tClass here
}
}
If you are interested in the reflection way, I found a partial solution in this great article: http://www.artima.com/weblogs/viewpost.jsp?thread=208860
In short, you can use java.lang.Class.getGenericSuperclass() and java.lang.reflect.ParameterizedType.getActualTypeArguments() methods, but you have to subclass some parent super class.
Following snippet works for a class that directly extends the superclass AbstractUserType. See the referenced article for more general solution.
import java.lang.reflect.ParameterizedType;
public class AbstractUserType<T> {
public Class<T> returnedClass() {
ParameterizedType parameterizedType = (ParameterizedType) getClass()
.getGenericSuperclass();
#SuppressWarnings("unchecked")
Class<T> ret = (Class<T>) parameterizedType.getActualTypeArguments()[0];
return ret;
}
public static void main(String[] args) {
AbstractUserType<String> myVar = new AbstractUserType<String>() {};
System.err.println(myVar.returnedClass());
}
}
There is no "clean" way to get the Generic Type argument from within the class.
Instead, a common pattern is to pass the Class of the Generic Type to the constructor and keep it as an inner property juste as done in the java.util.EnumMap implementation.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumMap.html
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/EnumMap.java
public class ContainerTest<T> {
Class<T> type;
T t;
public ContainerTest(Class<T> type) {
this.type = type;
}
public void setT(T t) {
this.t = t;
}
public T getT() {
return t;
}
public void doSomething() {
//There you can use "type" property.
}
}
No. It is not possible because of type erasure (the type parameters are compiled as Object + type casts). If you really need to know/enforce the type in runtime you may store a reference to a Class object.
public class ContainerTest<T> {
private final Class<T> klass;
private final List<T> list = new ArrayList<T>();
ContainerTest(Class<T> klass) {
this.klass = klass;
}
Class<T> getElementClass() {
return klass;
}
void add(T t) {
//klass.cast forces a runtime cast operation
list.add(klass.cast(t));
}
}
Use:
ContainerTest<String> c = new ContainerTest<>(String.class);
There is a way to get the runtime type of the type parameter by using Guava's TypeToken to capture it. The solution's disadvantage is that you have to create an anonymous subclass each time you need an instance of Container.
class Container<T> {
TypeToken<T> tokenOfContainedType = new TypeToken<T>(getClass()) {};
public Type getContainedType() {
return tokenOfContainedType.getType();
}
}
class TestCase {
// note that containerTest is not a simple instance of Container,
// an anonymous subclass is created
private Container<String> containerTest = new Container<String>() {};
#Test
public void test() {
Assert.assertEquals(String.class, containerTest.getContainedType());
}
}
The key of this solution is described in tha JavaDoc of TypeToken's constructor used in the code above:
Clients create an empty anonymous subclass. Doing so embeds the type parameter in the anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure.
If You can define like this
public class ContainerTest<T>
{
public void doSomething(T clazz)
{
}
}
Then it is possible

Categories

Resources