If I am writing a wrapper for a generic class, which I have tried to embed the type into at construction (as in this SO question):
class Foo<T> {
private T value;
private Class<T> type;
public Foo(Class<T> type, T value) {
this.value = value;
this.type = type;
}
public T getValue() {
return value;
}
public Class<T> getType() {
return type;
}
}
I have a list of instances of Foo, which I want to transform into a list of FooWrappers, along these lines:
List<Foo<?>> someListOfFoos = ...
List<FooWrapper<?>> fooWrappers = someListOfFoos
.stream()
.map(foo -> FooWrapper.from(foo))
.collect(Collectors.toList());
Is there any way to recover the type of each element in someListOfFoos when building each FooWrapper? Something along these lines:
class FooWrapper<T> {
private Foo<T> foo;
public static FooWrapper<?> from(Foo<?> toWrap) {
Class<E> type = toWrap.getType(); // i know this is wrong
return new FooWrapper<type>(toWrap); // this is very wrong
}
private FooWrapper(Foo<T> foo) {
this.foo = foo;
}
}
You just have to modify your FooWrapper#from slightly, by introducing a generic:
public static <E> FooWrapper<E> from(Foo<E> toWrap) {
return new FooWrapper<E>(toWrap);
}
Related
I'll try to keep this short. I'm trying to do something like this:
public enum Fruit {
APPLE("Apple", appleHelper::doAppleThing),
ORANGE("Orange", orangeHelper::doOrangeThing);
private String name;
private Function<String, List<T>> fruitFunction;
Fruit(String name, Function<String, List<T>> fruitFunction) {
this.name = name;
this.fruitFunction = fruitFunction;
}
public String getName() {
return name;
}
public <T> List<T> applyFruitFunction(String someString) {
return fruitFunction.apply(someString);
}
}
Such that later, I can have a method like
private <T> List<T> doFruitThing(String someString, Fruit fruit) {
List<T> transformedFruits = fruit.applyFruitFunction(someString);
if (transformedFruits.isEmpty()) {
throw new FruitException("There was no fruit of type " + fruit.getName());
}
return transformedFruits;
}
There's two problems I'm running into here.
doAppleThing and doOrangeThing are not static methods, and ideally will stay that way, and I can't find any way of creating a local instance of appleHelper and orangeHelper to make the method reference work.
Even if I were to make the methods static, enums can't have Type parameters, so there's no way to have Function<String, List<T>> fruitFunction as a field.
Is there a way this can be done? Or a better approach to this?
Enum values can have their own method implementations. So I would write this as:
public enum Fruit {
APPLE("Apple") {
private final AppleHelper helper = new AppleHelper();
#Override
public <T> List<T> applyFruitFunction(String someString) {
return helper.doAppleThing(someString);
}
},
ORANGE("Orange") {
private final OrangeHelper helper = new OrangeHelper();
#Override
public <T> List<T> applyFruitFunction(String someString) {
return helper.doOrangeThing(someString);
}
};
private String name;
Fruit(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract <T> List<T> applyFruitFunction(String someString);
}
However, if you get to the point of needing per-instance state for enum instances, the thing you have is less and less an enum and more of just an abstract base class. It might be better to look into a more OO approach, using a factory/flywheel pattern for example, rather than being tied to a pure enum for this sort of thing. (It's hard to tell for sure because the code in the question is obviously just a simplified example.)
Good day SO people. I have a problem regarding returning the inner enum values of my enum. I do not know which return type to use. I have tried googling and bumped into some solutions the uses generics however, I still have no luck. I do not know if my question has a solution or probably I did a bad design. So here goes, below
is my enum.
public enum KEYS
{
A("value"),
B("value"),
C("value");
public enum KEYS_GROUP_A
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_A( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
public enum KEYS_GROUP_B
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_B( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
public enum KEYS_GROUP_C
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_C( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
private String value;
private PROPERTY_KEYS(String _value)
{
value = _value;
}
public String getVal()
{
return value;
}
public <?> getEnumValues(int x)
{
if ( 0 == x )
{
return KEYS.KEYS_GROUP_A.values();
}
else if ( 1 == x )
{
return KEYS.KEYS_GROUP_B.values();
}
else
{
return KEYS.KEYS_GROUP_C.values();
}
}
}
What I am trying to do is the getEnumValues() method. I have tried the return type <T extends Enum<T>> T but still an error occurs. Please tell if my design is bad or should not really be done. Please state some references. I'm willing to read and learn. Please shed some light! Thanks in advance!
The most specific type you can return is
public Enum<?>[] getEnumValues(int x)
You can return a more "useful" type if you define an interface like this:
interface HasVal { String getVal(); }
then make your enums all implement that interface, e.g.:
public enum KEYS_GROUP_A implements HasVal {
// ...
#Override public String getVal() { return value; }
}
Then you can return
public HasVal[] getEnumValues(int x)
and be able to invoke the getVal method on the instances:
for (HasVal val : getEnumValues(x)) {
System.out.println(val.getVal());
}
You can't use:
public <T extends Enum<T>> T[] getEnumValues(int x)
because this isn't satisfiable for a general T. For instance, I could define:
enum Blah {}
and then try to invoke:
Blah[] blah = getEnumValues(1);
That wouldn't be type safe, because at least one (well, all, actually) of the code paths return a value which is not covariant with Blah[].
I have an enumeration from which I am able to get either a String or a Class
public enum EditorialPageDataType {
BASIC_MODEL_INFORMATION("basic", BasicModelInformation.class),
GRADES("grades", Grades.class),
EXTERIOR_COLOURS("extColours", ExteriorColours.class);
private final String label;
private final Class<?> typeClass;
EditorialPageDataType(String label, Class<?> typeClass) {
this.label = label;
this.typeClass = typeClass;
}
public Class<?> getTypeClass() {
return typeClass;
}
public String getLabel() {
return label;
}
}
I want to create something like the following:
public T extract(EditorialPageDataType editorialPageDataType) {
return anotherClass.get(editorialPageDataType.getTypeClass());
}
I know I can do the following
public <T> T extract(EditorialPageDataType editorialPageDataType, Class<T> classType) {
return anotherClass.get(classType);
}
Where anotherClass is:
class anotherClass {
public <T> T get(Class<T> classToReturn) {
T objectOfTypeT = getObjectOfType(classToReturn);
return objectOfTypeT;
}
}
But I wanted to be able to pass in only one parameter if possible and have the type specified by the enumeration.
Pass the generic parameter through with the call:
public T extract(EditorialPageDataType editorialPageDataType) {
return anotherClass.<T>get(editorialPageDataType.getTypeClass());
}
This is my class structure.
public class Node<T> {
private T value;
public Node(T val) {
this.value = val;
}
public T evaluate() {
return value;
};
}
T can be Integer, Double, Date, Long or String.
Now, is there anyway I can get to know exactly what that type T is? Thanks.
You can invoke getClass() method on that generic variable and find out the class. Basically generics are erased at run-time, so an unbounded generic is nothing but java.lang.Object. So you can invoke all the method supported by Object class on that generic variable
At run-time, getClass() on generic object will return the actual class which was used to substitute the generic
For example
public class Node<T> {
private T value;
public Node(T val) {
Class<?> clazz = val.getClass();
checkType(clazz);
this.value = val;
}
public T evaluate() {
return value;
};
private void checkType(Class<?> c) {
if(c.getName().equals(Integer.class.getName())) {
//...
}
}
}
Much easier, use instanceof.
public class Node<T> {
private T value;
public Node(T val) {
checkType(val);
this.value = val;
}
public T evaluate() {
return value;
};
private void checkType(T val) {
if(val instanceof Integer) {
//...
}
}
}
Though there is already an accepted answer, I think it may be good to add one more answer:
As mentioned by #BaileyS, there is no way to get info of T in a place without an instance of T.
The solution greatly depends on why you want T, how you are using it. Normally, if we need the type of T for the logic (e.g. creating a new instance of T), it is usually done by providing the Class instance.
For example, you can make your Node class be:
public class Node<T> {
private T value;
private Class<T> valueType;
public Node(T val, Class<T> valueType) {
this.value = val;
this.valueType = valueType;
}
//.....
}
If you know that your node will store only Number you could restrict it.
public class Node<T extends Number> {
private final T value;
public Node(T val) {
this.value = val;
}
public T evaluate() {
return value;
};
public Class<? extends Number> type() {
return value.getClass();
}
}
Is there a way to find generic type in constructor?
public class geneticarg {
public static void main(String[] args) {
a<String> a1 = new a<String>("a");
a<String> a2 = new a<String>(null); // gives NPE
System.out.println(a1.getClazz());
}
}
class a<T> {
private Class<T> clazz;
private T element;
public a(T clazz) {
this.clazz = (Class<T>) clazz.getClass();
this.element = clazz;
// what if clazz is null ?
}
//getter and setter
}
EDIT : It is not necessary that always String comes.
You have to pass the type in the constructor. You can use a static factor to avoid having to set it twice.
A<String> a1 = A.wrap("a");
A<String> a2 = A.forClass(String.class);
class A<T> {
private final Class<T> clazz;
private final T element;
private A(T t, Class<T> clazz) {
this.clazz = clazz;
this.element = t;
}
public static <T> A<T> wrap(T t) {
return new A<T>(t, (Class) t.getClass());
}
public static <T> A<T> forClass(Class<T> clazz) {
return new A<T>(null, clazz);
}
//getter and setter
}
The only way to avoid type erasure in your case is to use generic superclass. You need to subclass your generic type and then you can access parametrized type, it is available via reflection API:
public abstract class a<T> {
private Class<T> clazz;
private T element;
public a(T obj) {
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
this.clazz = (Class<T>) type.getActualTypeArguments()[0];
this.element = obj;
}
}
class StringA extends a<String> {
public StringA(String obj) {
super(obj);
}
}
Peter is quite correct. I'd like to add some more info:
The instance of Class<T> passed into the constructor is called a type token.