I have a method call in a loop currently that does not compile:
for (Example example : Util.getExample(List.class)) {
// Do something with example
}
Util:
public class Util {
public <T> T getExample(Class<T> clazz) {
//...
}
}
The obvious fix is to cast the return from getExample to List<Example>. I'm wondering: is there is an alternative way to avoid the cast?
Further Information:
Posters asked for more information, so here goes...
I have built a framework around annotation processing that writes code to access and mutate class members (constructors, fields and methods). This framework backs both Parceler and Transfuse and allows me to, during compilation, identify a property and generate code to access or modify said property. For private properties (private constructors, private fields, private methods) I use a utility to perform these actions (Parceler's, Transfuse's) to break encapsulation via reflection.
Parceler has a feature to unroll collections during serialization in order to serialize members of the given collection. For private collections the InjectionUtil is used to access these properties within a loop:
for (Example example : InjectionUtil.getField(List.class, Container.class, container, "exampleField")) {
// ...
}
Which is the bug I'm currently faced with, and thus, why I'm asking about avoiding a cast. I'd prefer to not cast as I'd like to generically generate a bit of code to access a type and respect Java generics in the process.
If your getExample method is supposed to always return a list, then yes, change its return type to List<T>. But since you're passing List.class as an argument, it looks like you want to have a method that can return both lists and non-lists depending on which class object you pass it.
If so, that's not going to work the way you might be hoping. Your method in this case returns just List, the raw type. To make it return List<Example>, you'd have to pass it something like a hypothetical List<Example>.class, but there's no such thing. Generic type parameters are erased at compile time, so List<Example> and List<String> are really both the same class; they don't have separate class objects, so a class object argument can't tell your method what kind of list it should return.
You'll probably need to try a different design approach. Since this is clearly a simplified example, you might be able to get more help if you post more details about what you're actually trying to accomplish.
Guava's TypeToken can be used in this case because List<Foo>.class is not valid. TypeToken is used by creating an anonymous class. Because anonymous classes keep their generic signatures, this works.
for (Example foo : Util.getExample(new TypeToken<List<Example>>() {}) {
// do stuff
}
// utils
public <T> T getExample(TypeToken<T> typeToken) {
Type type = typeToken.getType();
// get example
}
TypeToken is more specific than just using the Class. You could also use the plain Type as a parameter so you can still feed it a Class. This is how Gson does it.
I think this is a design issue...
Since the method in Util you are calling is called getExamples it seems reasonable that it might just as well be fixed to return some collectionwhose elements are instance of the Example class.
It is reasonable to change getExamples to something like this?:
class Util {
public static <C extends Collection<? supper Example>> getExamples(final Supplier<C> factory) {
final C result = factory.get();
// here goes the code that adds the examples to the result collection
// using add or addAll.
return result;
}
}
So for-example if you wan to get a List<Example> using ArrayList<E> for implementation you would do like so:
List<Example> examples = Util.getExamples(ArrayList<Example>::new);
Try to pass the returned collection class object reference instead (eg. List.class, ArrayList.class) won't work as the code in getExamples will have a hard time (a) figuring out how to call the appropriate constructor using reflexion to instantiate the result (kinda of impossible if you pass just an interface class object such as List.class) and (b) casting the return from a raw type into a generic type with Example as element type. The latter is trivial however it is not as neat as it can be as it will generate a warning.
It is just more straight forward to delegate in the using code to indicate explicitly how to instantiate the result collection.
If you break away from returning a Collection and use methods like add and addAll in getExamples then perhaps you should borrow the Collectors framework from the java stream API.
Related
Let's suppose you're writing a library, and it is to act upon a client class that is passed to it (i.e. client code cannot be changed).
class ClientClass {
public GenericClientClass<AnotherClientClass> someField;
}
What I'm trying to do is instantiate someField through reflection. Something like:
class LibraryClass{
public instantiateAllFields(Object obj){
//iterate through all fields of obj.class, and instantiate them
}
}
The only requirement of the client's fields is that a constructor without arguments exists. (e.g. GenericClientClass() {} )
The purpose of this is to create a highly automated testing library, currently for my own purposes.
I've been able to implement the above for almost all cases (arrays, objects, primitives, generic arrays etc.); however, this particular case has stumped me.
field.getType().newInstance() does not work, since the generic type parameters are removed.
field.getGenericType() doesn't work, because it returns a type, not a class.
If It's a known generic class, I can create a special case to deal with it. For example:
Class<?> genClass = ((Class<?>)((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0]);
JArray jArray = new JArray(true,n,genClass);
field.set(object, jArray);
...I'm guessing I could do this for things like ArrayList, HashMap etc.
However, I would like to cover the general case, and be able to instantiate any generic class (with a single parameter, and a zero-argument constructor) that may be passed into the library.
Any ideas?
Note that the type of the generic parameter is known. I can get at it through field.getGenericType().
There's no such thing as "an instance of a parameterized type"; or, rather, there's no difference between instances of parameterized types with different type parameters. The type parameter is just something the compiler uses to enforce type correctness.
If you're instantiating it at runtime, the compiler is not in the loop. So you just have to create a "raw"/"wildcard"-typed instance, and cast it; and you have to own the problem of ensuring that the cast actually is safe.
Assuming GenericClientClass is not abstract, and has a constructor without parameters:
someField = (GenericClientClass<AnotherClientClass>) GenericClientClass.class.getConstructor().newInstance();
and deal with the resulting unchecked cast warning appropriately.
I have a generic class as follows:
MyClass<T>
{
....
}
Now, what I want create a single generic method,say for example public MyClass<T> getMyClassInstance(Type t){...}, in which I pass a type and this method gives an instance of MyClass with that type.
See the following examples.
If I call this method as follows, getMyClassInstance(Integer_type), then it returns the MyClass<Integer> instance.
Similarly, if I call this method as follows, getMyClassInstance(String_type), then it returns the MyClass<String> instance.
How shall I write this method? If it can't be done, is there any alternative way or another better way to do something like this?
For simple applications of this, you don't even need to pass in a Type or Class argument. Consider the following:
public <T> List<T> getList() {
return new ArrayList<>();
}
To use this is as simple as:
List<Integer> lst = getList();
The compiler will infer the type of the list desired.
Do note that you will get more flexibility from passing in a Type parameter, especially in cases where you may not know in advance what sort of List you want to get back. But this sort of syntax, IMHO, reads more naturally and may be suited to what you want to do. (I say "may" since you haven't provided a ton of details ...)
The Type class must carry the type parameter on it: Type<T>, so you can declare
<T> MyClass<T> getMyClassInstance(Type<T> t);
If you can't make that happen, then the compiler is blind.
currenty I'm facing a problem with generic classes in Java.
I have something like this:
public class GenericClass<T> {
T doSomething() {...}
Collection<String> getCollection() {...}
}
Now I instantiate an object of that class without the type parameter, since I'm not intereseted in that or I don't know it.
GenericClass obj = new GenericClass();
for (String str : obj.getCollection() { // won't work
...
}
The problem is, that the compiler does not simply throw away the information about the type-parameter, but also about the type of the Collection (String), although that's independent from the parameter.
Am I doing something wrong, or is that a restriction of Java? If so, why is that a restriction?
You're doing something wrong.
When you don't know the T type, you should just use a wildcard: GenericClass<?>. You can't do this when you're instantiating a new GenericClass, though, so just use Object:
GenericClass<?> obj = new GenericClass<Object>();
For backwards-compatibility reasons, it is deliberate that a class without any generic information at all (GenericClass without any <>) loses all generic type safety so it can be used safely with pre-generic code.
The following code works perfectly fine. Instead of directly extracting values from obj.getCollectionn(), it would be preferable to store it to some Collection variable and then access it.
GenericClass obj = new GenericClass();
Collection<String> c = obj.getCollection();
for (String string : c)
{
//Some complex Code
}
Creating an instance of a generic type without specifying the type parameter is a practice that should only ever be done by legacy code. Any new code that you are writing should not do this. This is called using a "raw type" and compromises all the compile-time type safety that you had written a generic class for in the first place.
Also, just a note that I hope you'll find helpful as well: if you plan to use your own value-based class instances in the Collection framework, you'll need to give some thought to providing a well-behaved implementation of equals() and hashcode(). Not doing this (and relying upon the default behavior of the Object class for equals() and hashcode()) may mean that your objects don't function well in your collections.
Is it possible to declare the type of a generic using a class object?
For instance, I would like to do something like this:
Class returnType = theMethod.getReturnType();
AttributeComponent<returnType> attComponent;
attComponent = new AttributeComponent<returnType>(returnType, attName);
attributeComponents.put(methodName.substring(3), attComponent);
Now I know obviously this is incorrect, but is there a way to achieve this?
EDIT: explaining a little bit
I'm using reflection to go through all getters and then generate a UI element for each property (the AttributeComponent class, which has a JComponent element and a JLabel). I would like to use generics in order to create a getValue() method that would return an object of the property type.
I do not know if there is a way to compile something like that, but it has little value.
Think that thanks to type erasure, the compiled classes do not use the Generics information. That is, doing a Set<String> a = new Set<String>(); is useful for checking the use of a at compile time, but not at runtime.
So, you want to instantiate a Generic whose type will be only known at runtime, but at runtime it will not be used.
I would say this can be achieved by defining the method return type as generic; but you need to pass the actual type as a class argument to use it like you've shown:
<T> T yourMethod(Class<T> returnType) {
// use <T> as generic and returnType to refer to the actual T class
/* ... */ new AttributeComponent<T>(returnType, attName);
}
It would be also useful to see the larger context for what you're trying to do. If you want AttributeComponent.getValue() to return some generic type T (which is the method return type), that's completely useless unless you know each method return type at compile time, otherwise T will be nothing more than an Object. In my example above, you call yourMethod with a class that you already know and the same type will be returned (or some AttributeComponent of that type or whatever).
I have a method which returns a List<Property<?>>.
Property is a type having one generic parameter:
public class Property<T extends Comparable<T>> { ... }
Having a list of mixed-typed properties, I cannot know what type parameter a specific element has.
I would like to do something like that:
List<Property<?>> list = getList();
for(Property<?> crt : list)
{
PropertyWrapper<?> crtWrapper = new PropertyWrapper(crt.getGenericType());
// I know this doesn't exist ----^
}
In one sentence: I need the PropertyWrapper to have the same generic template argument as the current Property does. Is there any way to do this?
I could apply a suggestion as stated in https://stackoverflow.com/a/3437930/146003 but even if I do this, how to instanciate the appropriate PropertyWrapper<XXX> then, only having an instance of Class<T>?
I can modify Property<?> if required. I also don't mind if reflection needs to be used (I assume it needs to be)
EDIT: I forgot something. In fact I cannot instanciate the wrapper by the line
PropertyWrapper<?> crtWrapper = new PropertyWrapper(crt.getGenericType());
because I have specialized subclasses (PropertyWrapper_String).
Now I see two possibilities:
1: Instanciate the class by string:
String strGenericType = "";
Class<?> wrapperClass = Class.forName("PropertyWrapper_" + strGenericType);
2: Is there any way to specialize a generic class without creating a subclass?
Many thanks in advance for your tips
Try creating the following method:
<T> PropertyWrapper<T> createWrapper(Property<T> property){
return new PropertyWrapper<T>(property);
}
Then call it as such.
List<Property<?>> list = getList();
for(Property<?> crt : list)
{
PropertyWrapper<?> crtWrapper = createWrapper(crt);
}
The reason the above works is that the generic type T is inferred from the argument and is locked down for the entire method. Unlike using <?> in the loop where each instance of <?> is inferred to be a different type.
Edit:
To deal with the issue of having a different class type depending on the class in the wrapper, consider a Map where the key is the class being wrapped and the value is the wrapper.
Map<Class<?>, Class<?>> myMap;
Then you could so something like this:
Class<?> wrappedType = property.getGenericType();
Class<?> wrapperClass = myMap.get(wrappedType);
PropertyWrapper<?> wrapper = (PropertyWrapper<?>) wrapperClass.newInstance();
Although you might need to do something like this if you need to pass an argument.
Constructor<?> constructor = wrapperClass.getDeclaredConstructor(property.getClass());
PropertyWrapper<?> wrapper = (PropertyWrapper<?>) constructor.newInstance(property);
If you have a Class<T> you can just take that class, create an instance by calling newInstance() on the class object and cast it to T.
The problem you have is getting the generic parameter of crt. If you have concrete subclasses of Property, e.g. StringProperty extends Property<String>, you can get the type using reflection. However, if you only create instances of Property<T> without concrete subclasses and you don't know where the elements of the list are created, AFAIK it is impossible to get the generic type (even if you know where the elements are created it might be impossible though).
Thus, the only way you might get the property wrapper to know the type of the property might be to store the type parameter (the class) in the property itself. Then the wrapper could query the property for its type/class member variable.
Edit: some explanation on why this is impossible or at least very hard.
The problem with generics is that due to type erasure the generic type is lost when you create a property using new Property<SomeType>(). There's just no runtime information that you could use to retrieve SomeType here.
If you have concrete subclasses (defining concrete generic types) you have reflection information available at runtime of what where the generic parameters of each class. Then you could get the actual class of each property and retrieve the reflection data for that class.
This would also be possible if you have methods or fields that define those types and return/hold references to a propery. However, I doubt you have that information since you seem to get some list and don't know exactly on where and how the elements of that list were created.
I further assume the properties' class is Property only, not a subclass. Thus the only way is to provide the runtime information yourself, i.e. by passing a reference to the type class as a constructor parameter.
Okay I'm going to answer myself.
I'm now passing an instance of Class<?> to the Property-class.
Then I extract the basic name of the property and simply cut away "java.lang." which is possibly as in most cases, I'm doing this to primitive data types - resp. their autoboxing classes.
Further, I just instanciate a new instance of the wrapper by name and pass the to be wrapped property as a parameter to the constructor which applys for that.
Here some code for the interested ones among you:
String template = "..."; // some package definition
for (Property<?> crt : bag)
{
String className = template + crt.getClassName();
Class<? extends PropertyWrapper<?>> wrapperClass = null;
wrapperClass = (Class<? extends PropertyWrapper<?>>) Class.forName(className);
Constructor<? extends PropertyWrapper<?>> constructor = wrapperClass.getConstructor(new Class<?>[] {Property.class});
PropertyWrapper<?> wrapper = constructor.newInstance(crt);
// Further operations using the wrapper
}
for simplicity, I left out the error handling part.
Rather than instantiating the wrapper from the call site, why not have the Property know how to create its own wrapper? Something like:
public class Property<T extends Comparable<T>> {
PropertyWrapper<T> newWrapper();
}
That only half-helps, though. Your real problem is that in a loop like yours:
List<Property<?>> list = getList();
for(Property<?> crt : list)
{
PropertyWrapper<?> crtWrapper = crt.newWrapper();
}
The fact that the PropertyWrapper and the Property have the "same" type isn't very helpful, since that type is just the unbound wildcard.
I really hate to give one of those "what are you really trying to do" answers, but -- what are you really trying to do? Generally speaking, once you get to an unbound wildcard, all hope is lost (unless you're willing to do unsafe, uncheckable casts or bend over backwards with reflection checks). One way around this is to put as much of the action within the Property<T> as possible,before you put that property in the List<Property<?>>. My newWrapper() is an example of this: it puts the action of creating a PropertyWrapper<T> into the Property<T> itself. If you wanted to register a callback for when the property changed, that's also something you may be able to do at each place you instantiate a non-wildcard Property<Whatever>. For instance:
Property<UserLogin> property = new Property<UserLogin>();
SomeListener<UserLogin> listener = whatever();
property.addListener(listener);
wildcardedPropertiesList.add(property);
This particular example probably won't help, but hopefully it'll give you applicable ideas.