Java Generics can't use wildcard with generic T - java

I have the following, small interface:
public interface EntityController<T> {
public void update( float elapsed, T applyTo );
}
Which I want to use in the following way:
private Map<Class<? extends GameObject>, EntityController<?>> registeredControllers;
public EntityController<?> getController(GameObject o) {
return registeredControllers.get(o.getClass());;
}
...
getController(myObj).update(elapsed, myObj);
The last line gives me the error that The method update(float, capture#1-of ?) in the type EntityController<capture#1-of ?> is not applicable for the arguments (float, GameObject)
Why is that? Basically, what I want to achieve is the following:
I know that each EntityController is responsible only for handling one specific type of class. Therefore, in the update method of it I will always have to cast my GameObject to the respective type, which is annoying, and I guess also generates some kind of overhead? I thought generics would be a nice way of solving the problem, allowing me to create specific controllers in the following manner:
public class MyController implements EntityController<MyType> {
public void update(float elapsed, MyType applyTo){}
}
Why isn't that possible?

To put it simply, you cannot assign a value to a wildcard type, because the actual type is unknown. So if the return type is EntityController<?>, you cannot assign to update's 2nd argument.
The easiest (but not 100% type safe) solution would be
private Map<Class<? extends GameObject>, EntityController<? extends GameObject>> registeredControllers;
#SuppressWarnings("unchecked")
public <T extends GameObject> EntityController<T> getController(T o) {
return (EntityController<T>) registeredControllers.get(o.getClass());
}

Related

When should I use a generic parameter and when should I use parent class as a parameter

what are the differences between the two? When should I use each?
Generic:
public static <T extends SomeClass> void doSomething(T class)
{
}
Parent class as a parameter:
public static void doSomething(SomeClass class)
{
}
Due to type erasure, both the methods are effectively the same.
Such a generic would only be useful if you're returning an instance of T from the method. A simple example would be casting an object stored somewhere to the expected type (this is unsafe, as we do no actual check if it is really and instance of T, but that is another story)
public static <T extends SomeClass> T get(String name) {
return (T) fancyLookup(name)
}
private static Object fancyLookup(String name) { ... }
So to answer your question:
What are the differences between the two?
Nothing, at runtime they are effectivly identical.
When should I use each?
Prefer the one without generics, as said they are the same, and introducing a generic where none is needed just complicates your code.

Generic return type of enum-method

Situation: May Field be a property of a Model which I want to observe (something similar to PropertyChangeListener). Field is defined as Enum. I want to call
someModel.getField(Field f).addObserver(FieldObserver<Something> observer)
the Observer's type ("Something") depends on the Field and I want to force typesafety. For example Field.FIRST_NAME would take a FieldObserver< String>.
First (working) approach:
I could already reach it by defining Field as generic class with public static final fields, instead of enum. So I have a Field, which I can use to force type safety like this:
public <E> Observable<E> getField(Field<? extends E> f)
with method in Observable<E>: void addObserver(FieldObserver<? super E> observer)
Now the following line causes a compile time error, which is what I want:
someModel.getField(Field.some_STRING_field).addObserver(INTEGERObserver)
Second (not working yet) approach:
I am trying now to implement the same behaviour with the enum class. One of my approach is:
public enum Field{
FIRST_NAME("firstName") {
#Override
public Observable<String> getObservable() {
return new Observable<String>();
}
},...
//every Field must implement:
public abstract FieldObservable.Observable<?> getObservable();`
}
//getField(Field f) of the Model-class:
public Observable<?> getField(Field f){
return f.getObservable();
}
Trying to add a FieldObserver of any type (also the correct one) gives me a compile time error like this:
addObserver (enumer.FieldObserver< capture< ?>>) in Observable cannot be applied
to (enumer.FieldObserver< java.lang.String>)
Can someone tell me how to make the enum-approach work? Also if someone has a better solution or concerns about the approaches, I will be thankful to hear it.
Unfortunately enums cannot be generic. This is because enum is an ordinary class that extends Enum, i.e. its definition looks like the following:
class MyEnum<E extends Enum<E>> extends Enum<E extends Enum> {}
So application programmer cannot add more generic parameter to this class.
I can suggest you the following work arounds:
Make your method generic, ie. define it in enum level as public <T> getField(Class<T> type). Override this method for each enum member. Then you can supply the type at any call of the method.
Do not use enum for this task. Create ordinary class with public static members and private constructor. if you want enum-like behavior implement your own static values() and valueOf().

Java Bounded Type Parameter in Enum

I am trying to create following enum.
public enum MyEnum{
LEAD {
#Override
public boolean isValid(Lead lead) { //compile error, asks to retain type as T
}
},
TASK {
#Override
public boolean isValid(Task task) { //compile error, asks to retain type as T
}
};
public abstract <T extends SObject> boolean isValid(T object);
}
Lead and Task classes both extend SObject. My intention is to basically let clients be able to use MyEnum.LEAD.isValid(lead) or MyEnum.TASK.isValid(task). Compiler shouldn't allow to pass other types.
Could someone help in understand why this is happening.
Thanks
You need to override the generic method with the same generic method. If you want to do what you are asking you need a generic class - which an enum cannot be.
The point being that I refer to the enum by the class reference - i.e.
final MyEnum myenum = MyEnum.LEAD;
Now if I call myenum.isValid() I should be able to call it with any SObject as defined by your abstract method.
The generic method definition that you have doesn't actually do anything. All it is doing is capturing the type of the passed in SObject and storing it as T. A generic method is commonly used to tie together types of parameters, for example
<T> void compare(Collection<T> coll, Comparator<T> comparator);
Here we do not care what T actually is - all we require is that the Comparator can compare the things that are in the Collection.
What you are thinking of is a generic class, something like:
interface MyIface<T> {
boolean isValid(T object);
}
And then
class LeadValid implements MyIface<Lead> {
public boolean isValid(Lead object){}
}
You see the difference is that you would have a MyIface<Lead> - you would have to declare the type of MyIface. In the enum case you only have a MyEnum.

AbstractFactory with generic types in Java: a design problem

I have the following 2 interfaces accordingly to abstract factory pattern:
public interface GenericObjectInterface<T extends Number>{
public T getResult();
}
public interface AbstractFactoryInterface{
public <T extends Number> GenericObjectInterface<T> createGenericObject();
}
I have an abstract class implementing GenericObject, but it's still unaware of the concrete type (it does only generic operations on Number):
public abstract class GenericAbstractClass<T extends Number> implements GenericObjectInterface<T>{ }
Then I have a series of concrete class extending that perform generic parameter substitution:
public class IntegerObject extends GenericAbstractClass<Integer>{
public Integer getResult(){}
}
....
Now, from inside an implementation of the factory I build the concrete type, that's implementing GenericObjectInterface but has lost it's generic parameter:
public class ConcreteFactory{
public <T extends Number> GenericObjectInterface<T> greateGenericObject(Class<T> c){
if (c.class.isInstance(Integer.class)){
IntegerObject obj = new IntegerObject();
//I would like to return obj
GenericObjectInterface<T> a = new IntegerObject(); //errror
GenericAbstractClass<T> a = new IntegerObject(); //errror
return a;
}else if (c.class.isInstance(Double.class)){
}
}
}
I would like to return obj that implements GenericObjectInterface but I don't know how can I do it.
how can I solve this?
I'm used to abstract factory but I've never used it with generics. Am I doing some mistakes in interpreting the pattern?
If your method returns an IntegerObject why don't you just return GenericObjectInterface<Integer>? You already know the parameter type.
In that case, just add a generic parameter to AbstractFactoryInterface, too:
public interface AbstractFactoryInterface<T extends Number> { ... }
public class ConcreteFactory implements AbstractFactoryInterface<Integer> { ... }
In your implementation the type of T would be inferred from the assignment, and thus you could do this:
GenericObjectInterface<Double> g = new ConcreteFactory().greateGenericObject();
In that case T would be Double but you'd use Integer internally, resulting in this:
GenericObjectInterface<Double> a = new IntegerCell();
Since the compiler can't ensure that T will always be of type Integer it won't allow you to do that assignment.
Abstract factory is characterized by the factory method returning an interface or abstract class reference instead of the concrete reference. It does not extend to type parameters.
Think of it this way: should you be able to do this?
public class ConcreteListFactory {
public <T> List<T> createList() {
return new ArrayList<String>();
}
}
What if the caller wanted a List<Integer>?
If you want your factory to return a generified type, you should have your concrete class accept the type parameter. Otherwise have your factory method return a GenericObjectInterface<Integer>.
Alternatively, you could have your method accept a type token (Integer.class). For example:
public <T extends Number> GenericObjectInterface<T> createGenericObject(Class<T> clazz) {
if ( clazz.equals(Integer.class) ) {
return (GenericObjectInterface<T>) new IntegerObject();
}
}
This will result in an unchecked cast warning but you can prove to yourself that it is safe, and thus suppress the warning or ignore it.
Generally, factories are not implemented as generics because you can't examine the type of the generic to determine the type of object to create (you can't do T.getClass) which is why #Mark's example causes the class to be passed in as an argument.
I think, more usually you would have multiple concrete factories. One for each Number type that you intend to support.
public interface AbstractFactoryInterface<T extends Number> {
public GenericObjectInterface<T> createGenericObject();
}
class IntegerFactory implements AbstractFactoryInterface<Integer>...
class LongFactory implements AbstractFactoryInterface<Long>...
You could then create a Map<Class, AbstractFactoryInterface>...
Map<Class, AbstractFactoryInterface> myMap = ...;
myMap.put(Integer.class, new IntegerFactory());
myMap.put(Long.class, new LongFactory ());
casting is perfectly fine here. if c==Integer.class, then T=Integer, casting GOI<Object> to GOI<T> is absolutely correct. It is a checked cast because you have checked that T=Integer before casting, therefore the unchecked warning can be legitimately suppressed.

Is it possible to write a method that returns a class object of T?

If I have a base class such that
public abstract class XMLSubscription <T extends XMLMessage>
Is it possible to write a method in XMLSubscription that returns a class object of T?
The only possible solution that I came up with is to have each descendant of XMLSubscription have a method like:
public class XMLStatusSubscription extends XMLSubscription<XMLStatusMessage>
{
public Class <XMLStatusMessage> getExpectedMessageType()
{
return XMLStatusMessage.class;
}
}
Unfortunately - and yes, this is due to type erasure - there is no way to return the Class object without providing it at runtime somehow.
Fortunately this is not usually too difficult. Here's how I've typically done this / seen it done:
public abstract class XMLSubscription <T extends XMLMessage> {
private Class<T> messageType;
protected XMLSubscription(Class<T> messageType) {
this.messageType = messageType;
}
public Class<T> getExpectedMessageType() {
return this.messageType;
}
}
public class XMLStatusSubscription extends XMLSubscription<XMLStatusMessage> {
public XMLStatusSubscription() {
super(XMLStatusMessage.class);
}
}
As you guessed, T is erased by the compiler. When you instantiate the object it has no idea that's it's supposed to deal with XMLStatusMessage objects. Your base class would define the following template method, and 1.5's covariant return types would keep the compiler happy with the concrete subclasses:
public Class<T> getExpectedMessageType()
There is one meta-comment: this looks a lot like procedural code, where something calls getExpectedMessageType() and then takes action based on the return type. This might be better implemented using a Visitor pattern, with the visitor implementing "doSomething" methods for each of the subclasses of XMLMessage.

Categories