Get list of Enums from generic class - java

I have a class that is paramaterised with an extend of Enum.
public class MyClass<EnumType extends Enum> {
public MyClass(){
Enum<?>[] enums = EnumType.getEnumConstants();
}
}
The line:
Enum<?>[] enums = EnumType.getEnumConstants()
fails to compile with "can not resolve method".
How can I get to the base type and get the enums?
OTOH, if I do the following it works ok:
public void setEnumType(Class <? extends Enum> clazz){
Enum<?>[] enums = clazz.getEnumConstants();
}
I can't pass this into the constructor as it is a custom view which is directly inserted in the parent.

Owing to erasure, you have to pass an instance of the enum class to the constructor:
public class MyClass<EnumType extends Enum<EnumType>> {
// ^ don't forget this
public MyClass(Class<EnumType> c){
Enum<?>[] enums = c.getEnumConstants();
}
}
MyClass<YourEnum> m = new MyClass<>(YourEnum.class);
Or, you could pass YourEnum.values() directly. The risk there is that a caller can pass any array, not necessarily one with all values, without duplicates, in the right order etc.

Related

How to find all sub classes of implemented interface in java?

How to get Subclass object using implemented interface, if interface is used as Type Parameter for DynamoDBTypeConverter.(e.g. DynamoDBTypeConverter ).
public enum state implements EnumInterface{
CREATED("0");
}
public enum color implements EnumInterface{
GREEN("0");
}
public interface EnumInterface{
void getStatus();
}
public class DynamoDbEnumConverter implements DynamoDBTypeConvereter<String,EnumInterface>{
public EnumInterface unconvert(String value){
// find Object run time, EnumInterface represent color or stat
}
}
Get whether Enum interface represents color or state in unconvert method.
Check this page out: What are Reified Generics? How do they solve Type Erasure problems and why can't they be added without major changes?
Generics are erased in Java.
The only way you're going to get your code to work without hacking around is by providing one instance of the DynamoDbEnumConverter for each EnumInterface:
class DynamoDbEnumConverter<T extends Enum<T> & EnumInterface> implements DynamoDBTypeConvereter<String, T> {
private Class<T> enumType;
public DynamoDbEnumConverter(Class<T> enumType) {
this.enumType = enumType;
}
public EnumInterface unconvert(String value) {
return Enum.valueOf(enumType, value);
}
}
And then:
DynamoDbEnumConverter<Color> colorConverter = new DynamoDbEnumConverter<>(Color.class);

Get class of EnumSet's Enum

Is it possible to get the class of the Enum from a variable of type EnumSet.
Consider the following code:
enum Foo
{
FOO_0,
FOO_1,
}
<E extends Enum<E>> void fooBar(EnumSet<E> enumSet, Class<E> type)
{
EnumSet<E> none = EnumSet.noneOf(type);
// ...
}
void bar()
{
EnumSet<Foo> enumSet = EnumSet.of(Foo.FOO_1);
fooBar(enumSet, Foo.class);
}
Writing Foo.class in fooBar() seems redundant. I would like to extract the class from the enumSet inside fooBar() function. Is that even possible?
What I wish to do is just call fooBar(enumSet); and still be able to instantiate the none variable as EnumSet.noneOf().
Works for empty EnumSets also, and returns the correct enum type even when the element has a class body:
public static <T extends Enum<T>> Class<T> getElementType(EnumSet<T> enumSet) {
if (enumSet.isEmpty())
enumSet = EnumSet.complementOf(enumSet);
return enumSet.iterator().next().getDeclaringClass();
}

Generic type meaning for java.lang.Enum [duplicate]

I thought I understood Java generics pretty well, but then I came across the following in java.lang.Enum:
class Enum<E extends Enum<E>>
Could someone explain how to interpret this type parameter? Bonus points for providing other examples of where a similar type parameter could be used.
It means that the type argument for enum has to derive from an enum which itself has the same type argument. How can this happen? By making the type argument the new type itself. So if I've got an enum called StatusCode, it would be equivalent to:
public class StatusCode extends Enum<StatusCode>
Now if you check the constraints, we've got Enum<StatusCode> - so E=StatusCode. Let's check: does E extend Enum<StatusCode>? Yes! We're okay.
You may well be asking yourself what the point of this is :) Well, it means that the API for Enum can refer to itself - for instance, being able to say that Enum<E> implements Comparable<E>. The base class is able to do the comparisons (in the case of enums) but it can make sure that it only compares the right kind of enums with each other. (EDIT: Well, nearly - see the edit at the bottom.)
I've used something similar in my C# port of ProtocolBuffers. There are "messages" (immutable) and "builders" (mutable, used to build a message) - and they come as pairs of types. The interfaces involved are:
public interface IBuilder<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder>
public interface IMessage<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder>
This means that from a message you can get an appropriate builder (e.g. to take a copy of a message and change some bits) and from a builder you can get an appropriate message when you've finished building it. It's a good job users of the API don't need to actually care about this though - it's horrendously complicated, and took several iterations to get to where it is.
EDIT: Note that this doesn't stop you from creating odd types which use a type argument which itself is okay, but which isn't the same type. The purpose is to give benefits in the right case rather than protect you from the wrong case.
So if Enum weren't handled "specially" in Java anyway, you could (as noted in comments) create the following types:
public class First extends Enum<First> {}
public class Second extends Enum<First> {}
Second would implement Comparable<First> rather than Comparable<Second>... but First itself would be fine.
The following is a modified version of the explanation from the book Java Generics and Collections:
We have an Enum declared
enum Season { WINTER, SPRING, SUMMER, FALL }
which will be expanded to a class
final class Season extends ...
where ... is to be the somehow-parameterised base class for Enums. Let's work
out what that has to be. Well, one of the requirements for Season is that it should implement Comparable<Season>. So we're going to need
Season extends ... implements Comparable<Season>
What could you use for ... that would allow this to work? Given that it has to be a parameterisation of Enum, the only choice is Enum<Season>, so that you can have:
Season extends Enum<Season>
Enum<Season> implements Comparable<Season>
So Enum is parameterised on types like Season. Abstract from Season and
you get that the parameter of Enum is any type that satisfies
E extends Enum<E>
Maurice Naftalin (co-author, Java Generics and Collections)
This can be illustrated by a simple example and a technique which can be used to implement chained method calls for sub-classes. In an example below setName returns a Node so chaining won't work for the City:
class Node {
String name;
Node setName(String name) {
this.name = name;
return this;
}
}
class City extends Node {
int square;
City setSquare(int square) {
this.square = square;
return this;
}
}
public static void main(String[] args) {
City city = new City()
.setName("LA")
.setSquare(100); // won't compile, setName() returns Node
}
So we could reference a sub-class in a generic declaration, so that the City now returns the correct type:
abstract class Node<SELF extends Node<SELF>>{
String name;
SELF setName(String name) {
this.name = name;
return self();
}
protected abstract SELF self();
}
class City extends Node<City> {
int square;
City setSquare(int square) {
this.square = square;
return self();
}
#Override
protected City self() {
return this;
}
public static void main(String[] args) {
City city = new City()
.setName("LA")
.setSquare(100); // ok!
}
}
You are not the only one wondering what that means; see Chaotic Java blog.
“If a class extends this class, it should pass a parameter E. The parameter E’s bounds are for a class which extends this class with the same parameter E”.
This post has totally clarified to me these problem of 'recursive generic types'.
I just wanted to add another case where this particular structure is necessary.
Suppose you have generic nodes in a generic graph:
public abstract class Node<T extends Node<T>>
{
public void addNeighbor(T);
public void addNeighbors(Collection<? extends T> nodes);
public Collection<T> getNeighbor();
}
Then you can have graphs of specialized types:
public class City extends Node<City>
{
public void addNeighbor(City){...}
public void addNeighbors(Collection<? extends City> nodes){...}
public Collection<City> getNeighbor(){...}
}
If you look at the Enum source code, it has the following:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
#SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
}
First thing first, what does E extends Enum<E> mean? It means the type parameter is something that extends from Enum, and isn't parametrized with a raw type (it's parametrized by itself).
This is relevant if you have an enum
public enum MyEnum {
THING1,
THING2;
}
which, if I know correctly, is translated to
public final class MyEnum extends Enum<MyEnum> {
public static final MyEnum THING1 = new MyEnum();
public static final MyEnum THING2 = new MyEnum();
}
So this means that MyEnum receives the following methods:
public final int compareTo(MyEnum o) {
Enum<?> other = (Enum<?>)o;
Enum<MyEnum> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
And even more importantly,
#SuppressWarnings("unchecked")
public final Class<MyEnum> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<MyEnum>)clazz : (Class<MyEnum>)zuper;
}
This makes getDeclaringClass() cast to the proper Class<T> object.
A way clearer example is the one that I answered on this question where you cannot avoid this construct if you want to specify a generic bound.
According to wikipedia, this pattern is called Curiously recurring template pattern.
Basically, by using the CRTP pattern, we can easily refer to subclass type without type casting, which means by using the pattern, we can imitate virtual function.

Cast to super class type a "Class"

I have an interface
interface Inter extends Blah {
public void someMethod();
}
class Dummy {
Class<Blah> interfaceType;
public setInterfaceType( Class<Blah> input ) {
this.interfaceType = input;
}
}
class tester {
public void init() {
Dummy dummyObj = new DummyObj();
dummyObj.setInterfaceType( Inter.class ); //This complains that the type is not suitable
}
}
Compilation error:
The method setInterfaceType(Class) in the type Dummy is not applicable for the arguments (Class)
I tried casting input to Class<Blah> while calling setter but that isnt allowed either. Im not understanding why it doesnt accept a class of sub-class-type. Can anyone tell me whats happening here and how the setter can be invoked. The Dummy class is external so i cannot change it.
Generics are not covariant so you can't set to Class<Blah> object of type Class<Inter>. Think about it. If you would be able to use List<Fruit> list = new ArrayList<Apple>() then via list you would be able to add not only Apples but also other Fruits. Would that be OK?
To solve this problem try changing Class<Blah> to Class<? extends Blah>
You can also change your Dummy class to use generic type T
class class Dummy<T extends Blah> {
Class<T> interfaceType;
public void setInterfaceType(Class<T> input) {
this.interfaceType = input;
}
}
and use it like
Dummy<Inter> dummyObj = new Dummy();
dummyObj.setInterfaceType(Inter.class);
You most certainly means
Class<? extends Blah> interfaceType;
public setInterfaceType( Class<? extends Blah> input ) {
this.interfaceType = input;
}
Update
If the Dummy class can't be modified, then it is pretty dubius WHY there is such a setter method. But anyway, you may avoid the "generic type" check, by casting your argument to Class (without type argument), as in: dummyObj.setInterfaceType( (Class) Inter.class )

Declare attribute of type that extends 2 different interfaces

I would like to declare attribute that holds instance of class that implements 2 different interfaces. I have tried this syntax:
private <? extends Interface1 & Interface2> name;
and this:
private <T extends Interface1 & Interface2> T name;
None of those work. Is it possible? What's the syntax? I'm trying to avoid declaring another interface that inherits from both Interface1 and Interface2.
Edit:
The class containing this attribute should not have any type arguments. That is nothing like this:
public class MyClass<T extends Interface1 & Interface2>{
private T name;
...
}
It would not make any sense for those using the class. It is not expected neither logical not possible for that class to be generic.
That needs to go in the class declaration, such as:
public class TestG<T extends Cloneable & Serializable> {
private T name;
}
One alternative is to set it in a method (but not a variable)
public class TestG {
public <T extends Cloneable & Serializable> void method(T parameter) {
}
}
A variable cannot be generic.
private <T> T var;
is not possible - at which point is T defined? When accessing var, I cannot make much assumptions on what I used at assignment time.
Java allows generics on classes and on methods. So you can have
private <T implements Cloneable & Serializable> void setVar(T val);
and you can have a class-wide type T.
But always remember that in the end, it is implemented by type erasure. You can always emulate more complex logic using getters, setters and casts. When done properly, it will give you just as much type safety.
The simplest way to obtain a variable with the type safety you want is to just use two variables, and a setter to keep them in sync.
private Serializable vars;
private Cloneable vars;
will of course give you a good type safety. But yes, it needs 4 bytes of additional memory, and a setter.
Here's the casting approach you asked:
private Object internal_var;
// Implementation notice: do not remove this generic.
// Due to a Java limitation, we *do* want these two constraints!
public <T extends Serializable & Cloneable> void setVar(T val) {
internal_var = val;
}
public Serializable getSerializable() {
return (Serializable) internal_var; // Type checked in setter!
}
public Cloneable getCloneable() {
return (Cloneable) internal_var; // Type checked in setter!
}
// This is the way to use it in a generic getter:
public <T extends Serializable & Cloneable> T getVar(Class<? super T> cls) {
return (T) cls.cast(val);
}
Note that in order to use T in the getter, we do need to have a parameter involving T.
Assuming we know a class Example implements Serializable, Cloneable, we can then use
// This actually ensures we get an instance of `Example` out:
Example e = instance.getVar(Example.class);
You can declare that type parameter in your class declaration, or method declaration, if that is a local variable, and use that type instead: -
public class Demo<T extends Interface1 & Interface2> {
private T t;
}
or: -
public class Demo {
public <S extends Interface1 & Interface2> void demo(S param1) {
S param;
}
}
If i understand your question correctly, you want a generic class which implements both the inetrfaces.
declare a generic type argument in your class definition and make it as an instace variable type.
public class Implementor<T extends Interface1<T> & Interface2<T>> {
private T t;
}
EDIT:
you cannot declare a type argument at instance variable declaration like
private <T extends I1 &I2> T t; //this cant be achieved.
at method level though is possible.
public <T extends I1 & I2> void method(T t){
}

Categories