How can I get the values of an "enum" in a generic?
public class Sorter<T extends Enum<?>> {
public Sorter() {
T[] result = T.values(); // <- Compilation error
}
}
On the other hand, I can query the values() for Enum class:
enum TmpEnum { A, B }
public class Tmp {
void func() {
T[] result = TmpEnum.values(); // <- It works
}
}
Class::getEnumConstants
You cannot directly get it from T because generics are erased by the Java compiler so at runtime it is no longer known what T is.
What you can do is require a Class<T> object as constructor parameter. From there you can get an array of the enum objects by calling Class::getEnumConstants.
public class Sorter<T extends Enum<T>> {
public Sorter(Class<T> clazz) {
final T[] enumConstants = clazz.getEnumConstants();
}
}
another way is using interface
public interface Sorter{
default public void sorting(){
Sorter[] list=this.getClass().getEnumConstants();
}
}
use
enum TmpEnum implements Sorter { A, B }
Related
Example code similar to my code.
public interface Builder<B, A> {
B build(A a);
}
public class ClientBuilder implements Builder<String, Integer> {
#Override
public String build(Integer i) {
return i.toString();
}
}
public abstract class Client<B> {
protected abstract <A> Builder<B, A> getBuilder();
}
public class ClientClient extends Client<String> {
#Override
protected Builder<String, Integer> getBuilder() {
return null;
}
}
In my ClientClient class I get a warning that says the following:
Unchecked overriding: return type requires unchecked conversion.Found 'Builder<java.lang.String,java.lang.Integer>', required 'Builder<java.lang.String,A>
Is there something I can do to get rid of this error?
I could use #SuppressWarnings("unchecked"), but that doesn't feel right.
In my example A is always an Integer but in my real code A can be one of two objects.
I guess I could also have two methods in my interface like this:
public interface Builder<B> {
B build(Integer i);
B build(String s);
}
This isn't overriding the method correctly:
protected Builder<String, Integer> getBuilder() {
return null;
}
You're missing the type variable.
Either declare it correctly:
protected <A> Builder<String, A> getBuilder() {
return null;
}
or change the class declaration to allow you to provide the second type parameter:
public abstract class Client<B, A> {
protected abstract Builder<B, A> getBuilder();
}
This question already has answers here:
Get generic type of class at runtime
(30 answers)
Closed 7 years ago.
I'd like to find a hack to infer the actual generic instance of another instance's var in runtime, without:
Changing my needed method signature (adding the helper parameter Class<T>, the obvious way)
Having to instanceof all possible subtypes in a hardcoded way
MyInterface<? extends Number> myInterface = whateverReturnsWildcardDoubleInterface();
Class<?> type = inferInstanceType(myInterface);
assert type == Double.class;
/** This is the method that represents the code I am looking for with the conrete signature**/
public <T extends Number> Class<T> inferInstanceType(MyInterface<T> myInterface){
return T.class; //Concrete T (can or cannot be the very Number)
}
Ideally, it should return Double when T is particular subtype Integer,Double.. and Number when T is Number
I checked reflection, several "TypeResolver"/"GenericResolver" libs (as the one in Spring or others in Github), but I cannot fin a way to hack it.
EDIT: I reached the conclusion that he only feasible way to do that would be some kind of very complex reflection through the stack trace up to the acutal line that passes the type in the very instantiation
EDIT2: I know it's stupid... but I solved it by simply adding a T getT() method to my interface, so I could return myInterface.getT().getClass()
Disclaimer: This solution is provided as a hack tailored to my understanding of your setup, i.e. one generic interface with a single type parameter, multiple classes, which are not themselves generic, directly implementing this one interface alone, and implementing no other generic interfaces, directly or indirectly.
Assuming that all of the above is true, there is a relatively straightforward way of hacking a solution: calling getClass().getGenericInterfaces() returns a Type object that provides the actual type with which your generic interface has been instantiated.
interface MyInterface<T extends Number> {
T getVal();
}
class DoubleImpl implements MyInterface<Double> {
public Double getVal() {return 42.42; }
}
...
public static void main (String[] args) throws java.lang.Exception {
MyInterface<? extends Number> x = new DoubleImpl();
Type[] ifs = x.getClass().getGenericInterfaces();
System.out.println(ifs.length);
for (Type c : ifs) {
System.out.println(c);
Type[] tps = ((ParameterizedType)c).getActualTypeArguments();
for (Object tp : tps) {
System.out.println("===="+tp); // <<== This produces class java.lang.Double
}
}
}
Demo.
As assylias pointed out, Java's erasure will make that information unavailable at runtime - and thus a need for a hack.
On the assumption that myInterface has a getter for T, as in, MyInterface.getValue():T (or the hack would be to add it) you could do something like this (ignoring the possibility that getValue() could return null):
public <T extends Number> Class<T> inferInstanceType(MyInterface<T> myInterface){
return myInterface.getValue().getClass()
}
Below is the full implementation
public class Q34271256 {
public static interface MyInterface<T> {
T getValue();
}
public static class MyDoubleClass implements MyInterface<Double> {
private final Double value;
public MyDoubleClass(Double value) {
this.value = value;
}
#Override
public Double getValue() {
return value;
}
}
public static class MyIntegerClass implements MyInterface<Integer> {
private final Integer value;
public MyIntegerClass(Integer value) {
this.value = value;
}
#Override
public Integer getValue() {
return value;
}
}
#SuppressWarnings("unchecked")
public static <T extends Number> Class<T> inferInstanceType(MyInterface<T> myInterface){
Number value = myInterface.getValue();
if (value == null) return null;
return (Class<T>)value.getClass();
}
public static void main(String...args) {
List<MyInterface<? extends Number>> list = Arrays.asList(
new MyDoubleClass(1.1),
new MyIntegerClass(5)
);
for (MyInterface<? extends Number> myInterface : list) {
Class<?> type = inferInstanceType(myInterface);
System.out.printf("%s inferred type is %s\n",
myInterface.getClass().getName(),
type.getName());
}
}
}
And the output should look something like this:
MyDoubleClass inferred type is java.lang.Double
MyIntegerClass inferred type is java.lang.Integer
With this code:
enum MyEnum {
A(1, 2),
B(3, 4);
private final int a;
private final int b;
MyEnum(int a, int b) {
this.a = a;
this.b = b;
}
}
class GetValuesFromEnum<E extends Enum<E>> {
public void printValues() {
// This causes "cannnot find symbol" error during compilation
for (E value : E.values()) {
System.out.println(value);
}
}
}
public class Main {
public static void main(String[] args) {
new GetValuesFromEnum<MyEnum>().printValues();
}
}
Calling values() on generic enum causes an error in compile time. Is it possible to somehow retrieve values of generic enum?
in addition to #Tagir Valeev's answer, another way to retrieve enum values at runtime is through java.lang.Class.getEnumConstants() method
public void printValues(Class<? extends Enum<?>> enumCls) {
for(Object obj: enumCls.getEnumConstants()) {
System.out.println(obj);
}
}
You can modify your code in the following manner:
class GetValuesFromEnum<E extends Enum<E>> {
private Class<E> clazz;
public GetValuesFromEnum(Class<E> clazz) {
assert clazz.isEnum();
this.clazz = clazz;
}
public void printValues() {
for (E value : EnumSet.allOf(clazz)) {
System.out.println(value);
}
}
}
public class Main {
public static void main(String[] args) {
new GetValuesFromEnum<>(MyEnum.class).printValues();
}
}
To be able to access enum values in runtime, you should know the class in runtime (for example, store the Class object in the field). Generic parameter is not enough due to erasure. Also note the usage of EnumSet.allOf: usually it's very cheap way of getting all the enum constants as it reuses internal enum constants array instead of copying it.
I am with a sort of trouble when using java generics in the visitor pattern.
My code is something like that:
public interface MyInterfaceVisitor<A, B> {
public A visitMyConcreteObject(MyConcreteObject object, B parameter);
}
public interface MyObject {
public <A, B> A accept(MyInterfaceVisitor<A, B> visitor, B parameter);
}
public class MyConcreteObject implements MyObject {
#Override
public <A, B> A accept(MyInterfaceVisitor<A, B> visitor, B parameter) {
return visitor.visitMyConcreteObject(this, parameter);
}
}
public class MyConcreteVisitor implements MyInterfaceVisitor<????> {
#Override
public <X extends C> X visitMyConcreteObject(MyConcreteObject object, Class<X> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
// This method is the entry point of the MyConcreteVisitor.
public <X extends C> void someOtherMethod(Class<X> parameter) {
MyObject m = ...;
X x = m.accept(this, parameter);
...;
}
}
public class C {}
public class Dog extends C {}
public class Cat extends C {}
public class Client {
public static void main(String... args) {
MyConcreteVisitor v = new MyConcreteVisitor();
v.someOtherMethod(Cat.class);
v.someOtherMethod(Dog.class);
}
}
// We have other implementations of the visitor that does not matters, like this one.
public class SomeOtherConcreteVisitor implements MyInterfaceVisitor<String, Integer> {
#Override
public String visitMyConcreteObject(MyConcreteObject object, Integer parameter) {
return "foo";
}
}
I need to find what is the generic signature in the ???? that makes the code compilable allowing the overriden method in MyConcreteVisitor class to match the signature in MyInterfaceVisitor interface.
I can't change the signature of the visitMyObject in the MyInterfaceVisitor interface, nor its generics. This happens because others implementations of MyInterfaceVisitor exists and their generics have nothing to with the ones from MyConcreteVisitor.
The MyConcreteVisitor class should not have a generic per-se, so the compiler must allow a MyConcreteVisitor v = new MyConcreteVisitor(); without generating the unchecked or rawtypes warning.
If I change the concrete visitMyObject to public C visitMyObject(MyObject object, Class<? extends C> parameter) and declare the ???? as <C, Class<? extends C>>, I would need to add a cast in the someOtherMethod.
How to define the generic type making it compilable without getting the unchecked or rawtypes warning, changing the interface or adding a cast? Is this even possible in java or I am abusing the generics too much?
The issue is that your implementation is trying to introduce another type parameter X extends C to the method visitMyConcreteObject and resolve the B parameter with it. You can't make visitMyConcreteObject generic with X but try to resolve B with a type parameterized by X, e.g. Class<X>, because B is resolved at the class declaration but X is only declared by a method of the class.
From what I can see, you have two options. Either make MyConcreteVisitor generic on X:
public class MyConcreteVisitor<X extends C> implements MyInterfaceVisitor<X, Class<X>> {
#Override
public X visitMyConcreteObject(MyConcreteObject object, Class<X> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
}
Or get rid of X and lose type safety (beyond the concrete type C):
public class MyConcreteVisitor implements MyInterfaceVisitor<C, Class<? extends C>> {
#Override
public C visitMyConcreteObject(MyConcreteObject object, Class<? extends C> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
}
i think this is what you are looking for:
public class MyConcreteVisitor implements MyInterfaceVisitor<Object,Class<?>> {
#Override
public Object visitMyConcreteObject(MyConcreteObject object, Class<?> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
// This method is the entry point of the MyConcreteVisitor.
public <X> void someOtherMethod(Class<X> parameter) {
MyObject m = ...;
X x = parameter.cast(m.accept(this, parameter));
...;
}
}
In the following:
public interface SomeInteface<A, B> {
public B doSomething(A a);
}
I want to implement a version where the method doSomething returns the parameter a back.
I tried a Holder class;
class Holder<A> {
public A value;
public(A a){this.value = a;}
}
and return Holder. However, I am not sure how to define an implementation class of SomeInterface so that I am able to do this.
The following does not even compile:
public class SomeImplementation<X> implements SomeInterface<T> {
private class Holder<A> {
public A value;
public class Holder<A>{
public A value;
public(A a){this.value = a;}
}
}
class Implementation<A, Holder<A>> implements SomeInterface<A, Holder<A>>{
public Holder<A> doSomething(A a){
//do stuff
return new Holder(a);
}
}
}
What am I messing up here?
It needs to be
class Implementation<A> implements SomeInteface<A, Holder<A>>{
public Holder<A> doSomething(A a){
//do stuff
return new Holder<A>(a);
}
}
In the classname you define the generic variables and their constraints. You don't need a Holder variable.
I don't understand why you make it so difficult. You say
I want to implement a version where the method doSomething returns the
parameter a back.
Well, you can do just that:
public class SomeImplementation<A> implements SomeInterface<A, A> {
public A doSomething(A a) {
// do stuff
return a;
}
}
No need for a Holder class.
The interface SomeInterface does not put any constraints on the type parameters, so there's no reason why they can't be the same.
Alternatively, you can allow your implementation to be parameterized with two different types A and B where A extends B (could be useful in some cases):
public class SomeImplementation<A extends B, B> implements SomeInterface<A, B> {
public B doSomething(A a) {
// do stuff
return a;
}
}