Hello I try pass to interface as parameter Enum object, and after this parse him to List<Enum> in body default function interface. So my interface looks like below
public interface SpecificObject<T extends Enum<T>>{
default List<Enum> asMyList(){
List<Enum> list = Arrays.asList(T.values()); // not works
return list;
}
}
After this I have a plane use in this way
class SomeObject implements SpecificObject<MyEnum>{
public SomeObject()
// dont' must Overwrite because I use as default
}
And somewhere in code usage, just as below
SpecificObject specificObject = new someObject SomeObject();
List<Enum> list = someObject.asMyList();
Is it possible in JAVA 8?
Step-by-step:
public static <T extends Enum<T>> List<T> getEnumConstants(T object) {
assert object != null;
Class<T> type = object.getClass();
T[] constants = type.getEnumConstants();
return Arrays.asList(constants);
}
Not tested, but this looks workable. The List is however as inflexible as the original T[].
Packing the function in an interface as default method will not bring any advantage.
Note Class.getEnumConstants is not typed for Enum, and will yield null for non-enums.
(When staying in one specific Enum, EnumSet (a kind of bitset) and EnumMap (a kind of array) is often quite efficient and fast.)
Related
Suppose I have two methods:
public Set<String> method1()
public List<String> method2()
How do I make a generic method off this? Specifically, I'm looking to genericize the "Set" and "List".
Here's an attempt that didn't work:
public static <T extends Collection> T<String> genericMethod
It's showing a compiler error: Type "T" does not have type parameters.
As far as the signature goes, it would be
public static <T extends Collection<String>> T genericMethod() {
...
}
Presumably, genericMethod is going to create an instance of T at some point and return that, rather than just returning null (that wouldn't be very useful, would it?), but there is no guarantee that T has any constructors at all. And due to type erasure, the runtime wouldn't know what type to create anyway. To work around this, the method would also need to accept a parameter that tells it how to create a T:
public static <T extends Collection<String>> T genericMethod(Supplier<? extends T> tSupplier) {
...
}
Now, rather than saying new T(), which is invalid, you do tSupplier.get() to get a T.
If the caller wants a Set<String>, for example, they would do:
Set<String> set = genericMethod(HashSet::new);
Note that the specific implementation of the collection is now specified by the caller, rather than hidden as an implementation detail of genericMethod. This is inevitable, as the specific type of collection (T) is now unknown to genericMethod.
for performance reasons I need to use arrays to store data. I implemented this in a generic fashion like this (see this answer):
import java.lang.reflect.Array;
public class SimpleArray<T> {
private T[] data;
#SuppressWarnings("unchecked")
public SimpleArray(Class<T> cls, int size) {
this.data = (T[]) Array.newInstance(cls, size);
}
public T get(int i) {
return data[i];
}
}
The problem is that I need the involved Class<?>es. However, I might have a more complex class hierarchy containing generics:
public class Outer<T> {
public class Inner {
}
}
I would like to initialize the array as I would with an ordinary class:
SimpleArray<Integer> intArray = new SimpleArray<>(Integer.class, 10);
intArray.get(0);
SimpleArray<Outer<Integer>> outerArray;
// how to initialize this?
SimpleArray<Outer<String>.Inner> innerArray;
// how to initialize this?
I read the post on how to (not) get the Class of something generic (here) but the bottom-line seems to be that everything is type-safety related syntactic sugar.
My question is the following: How can I create instances of the SimpleArray classes above while avoiding as much ugliness as possible?
There are two issues here.
Do you really need to pass in a Class? In this case, no. Your class does not actually need to know the element type at runtime to do its job. For example, you can just do:
public class SimpleArray<T> {
private Object[] data;
public SimpleArray(int size) {
this.data = new Object[size];
}
#SuppressWarnings("unchecked")
public T get(int i) {
return (T)data[i];
}
}
If you really needed a Class<T>, how would you get one? Well, first you need to ask yourself, what are you going to use this for? There will never be a "true" Class<T> for a non-reifiable type T because with a Class<T> you can do things like .isInstance() to check whether something is an instance of T at runtime; but of course it's not possible to check instance-of with non-reifiable types at runtime.
In this case, you're only going to pass it to Array.newInstance(), and Array.newInstance() uses the raw type anyway (it does not care about the compile-time type of the Class parameter -- the parameter type is Class<?> -- it only uses the runtime value of the Class object), it is sufficient to simply coerce a Class object representing the raw type to the appropriately-parameterized Class type:
(Class<Outer<Integer>>)(Class<?>)Outer.class
You seem to be trying to make a class that wraps an array and provides a method to get elements. The class Arrays.ArrayList does exactly that already, so there is no need to reinvent the wheel. It works as follows:
List<String> list = Arrays.asList(new String[30]);
list.set(3, "foo");
System.out.println(list.get(3));
You can't use Arrays.asList to produce a List<T> if the type T is generic without suppressing a warning because it is not possible to create a generic array. You can write a helper method to do this for you though.
#SuppressWarnings("unchecked")
public static <T> List<T> newArray(int size) {
return (List<T>) Arrays.asList(new Object[size]);
}
You can use the returned List to get and set elements without having to cast, even if the type T is generic. For example:
List<List<String>> list = newArray(30);
list.set(4, Arrays.asList("A", "B", "C"));
System.out.println(list.get(4));
I am currently making a library which is an utility for me to handle something which is not associated with the question (I am implicitly not saying the subject because it is not really important), however it does use reflection.
I am retrieving all declared and inherited methods from a class, which currently works fine and is not the issue. But the thing is, I need to do this as well for sub-classes since those inherit over like methods do (however you cannot override those like methods).
The problem that I am facing that it will use the same algorithm but there will be on difference, instead of calling clazz.getDeclaredMethods() I need to call clazz.getMethods. What is the best way too approach this, and I kind of need to return Class[] and Method[] in the method signature as well.
Normally I would look for a shared superclass, but in this case I prefer to the have Class[] and Method[] accordingly. For starters, I did some research and found some shared superclasses:
GenericDeclaration
AnnotatedElement
Since I need both Class[] and Method[] arrays I am thinking something
like generics, so the method would look like:
public static <T extends GenericDecleration> T[] getT () {
}
As mentioned by dasblinkenlight this will not work since the method doesn't take any arguments and cannot check whether to retrieve Class or Method objects.
But how would I detect whether I need to call getDeclaredMethods or getDeclaredClasses?
What is the best approach on how to do this without duplicating a lot of code? I really tried to explain myself here, but if it is still unclear what I am doing please feel free to ask away!
Thank you very much in advance!
After messing around with this, I have found a solution that totally fits my needs. This is a combination of generics and #dasblinkenlight's solution, like so:
public interface DeclExtractor<T extends GenericDecleration> {
public T[] extract (Class clazz);
public Class<? extends T[]) getGenericClass ();
DeclExtractor<Method> methodExtractor = new DeclExtractor<Method>() {
#Override
public Method[] extract (Class clazz) {
return clazz.getDeclaredMethods();
}
#Override
public Class<? extends Method[]> getGenericClass () {
return Method[].class;
}
}
// Same for Class
}
Now the method which also will return the correct type so you dont have to manually cast all GenericDeclaration to your original object type. My issue was that I used a collection for it and not the correct array:
public <T> T[] getAll (final DeclExtractor<T> extractor, Class<?> clazz) {
T[] declaration = extractor.extract (clazz);
//.. The algorithm..
// Return an instance of a collection as array (I use a set in my implementation)
final Object[] objects = myCollection.toArray();
return Arrays.copyOf(objects, objects.length, extractor.getGenericClass());
}
Technically you do not need the getGenericClass method in the interface, but I am using extract directly in a loop so I cannot pull the class of that, however, you can.
Hopefully this helps someone in the future :) Thanks again to #dasblinkenlight for the inspiration!
Your getT needs to get some input in order to decide what to do.
What about a method which can takes an enum as argument to determine whether it needs to get classes or methods? (from a comment)
There is a better approach: define an interface that performs the appropriate extraction, and make two instances of it - one for extracting classes, and one for extracting methods:
public interface DeclExtractor {
GenericDecleration[] extract(Class cl);
final DeclExtractor forClasses = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted classes
}
};
final DeclExtractor forMethods = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted methods
}
};
}
Now you can rewrite your getT to take an "extractor", like this:
public static GenericDecleration[] getT (DeclExtractor extractor, Class cl) {
...
// When it's time to get components of the class, make this call:
GenericDecleration[] components = extractor.extract(cl);
...
}
To initiate a call to getT, pass DeclExtractor.forClasses or DeclExtractor.forMethods:
GenericDecleration[] c = getT(DeclExtractor.forClasses);
GenericDecleration[] m = getT(DeclExtractor.forMethods);
I would like to write a generic method that takes a bounded parameter that extends Enum. For example, if I have an Enum as follows:
public enum InputFlags{
ONE (0000001),
TWO (0000002),
THREE (00000004);
public final int value;
InputFlags(int value){
this.value = value;
}
}
I can then do the following:
for (InputFlags ifg : InputFlags.values()){
// Do something with ifg
}
However if I try to do the above in a generic method whose return parameter is bounded, I cannot access the values() method:
public static <T extends Enum> T getFlags(int f){
T.values(); // NOT allowed, even though I have bounded by extending Enum.
}
It seems as though I cannot access values() in the generic method. Is this a peculiarity of Enums or is there a way round this?
values() is a very strange thing in Java. Look in the documentation for Enum - values() isn't even there! values() is not a method of Enum at all. Instead a static method called values() is implicitly added to every class extending Enum. But the values() method for one enum is different from the values() method in another enum.
The fact that T extends Enum means that if t has type T you can call instance methods from Enum on t. You can't call static methods of Enum (and even if you could, values() doesn't exist anyway!)
values() is only useful when you know the actual enum by name. It cannot be used when you only have a type parameter T.
The way around this problem is to pass a Class object. Like this:
public static <T extends Enum<T>> T getFlags(Class<T> clazz, int f){
T[] array = clazz.getEnumConstants(); // This is how you can get an array.
Set<T> set = EnumSet.allOf(clazz); // This is how you can get a Set.
}
values() is a static method inserted by the compiler in the InputFlags class. Thus, it is not possible to use T.values(), especially since T is a generic type. However, if you can get the Class object of T (usually via getClass(), or by passing it to getFlags(int f, Class<T> clazz)), you can use Class#getEnumConstants() on that object.
This is a peculiarity of static methods. There is no way in Java, with generics or otherwise, to define an interface that applies to static methods, ie. that a class should/must implement a static method.
Also, type erasure (among other things) prevents you from using a type variable T as a type name in a static method invocation expression.
I have a bunch of classes in java that all implement an interface called IdObject (specifying a getId() method). Moreover, they also all implement Comparable<> with themselves as type parameter, so they are all comparable to themselves.
What I'd like to do is declare a list of such objects, fill it, then sort it and call getId() on them. So my code looks like this:
List<? extends IdObject & Comparable<?>> objectList = null;
if (foo) {
objectList = new ArrayList<TypeA>();
...
} else if (bar) {
objectList = new ArrayList<TypeB>();
...
}
if (objectList != null) {
Collections.sort(objectList);
for (IdObject o : objectList) {
System.out.println(o.getId());
}
}
Basically my problem lies in the first line -- I want to specify two "constraints" for the type because I need the first one to make sure I can print the ID in the loop and the second one to make sure I can use Collections.sort() on the list.
The first line does not compile.
Is there a way to make this work without specifying a generic type without type parameters and using unchecked operations? I could also not find an example of this on the internet.
Greetings
List<? extends IdObject & Comparable<?>>
This type of multiple bounded type parameters is only possible in class and method signatures, I'm afraid.
So I guess the closest you can get is to define an interface:
public interface MyInterface extends IdObject, Comparable<MyInterface>
And declare your list like this:
List<? extends MyInterface> objectList = null;
How about creating antoher type ;
public CompIdObject extends IdObject implements Comparable {
...
}
and use this type for your generics ?
List<? extends CompIdObject<?>> objectList = null;
I've wanted to do similar things before on fields as well, but it can't be done (perhaps someone could elaborate on whether this is a technical restriction or a design choice, I'm not sure.)
The way forward would be to design an interface that extends the IdObject and Comparable, then use that in your generic list definition.