Java Bounded Type Parameter in Enum - java

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.

Related

Java Generics can't use wildcard with generic T

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());
}

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 Generics - Bridge method?

Something called the "bridge method" concept related to Java Generics made me stop at a point and think over it.
Btw, I only know that it occurs at the
bytecode level and is not available
for us to use.
But I am eager to know the concept behind the "bridge method" used by the Java compiler.
What exactly happens behind the scenes and why it is used?
Any help with an example would be greatly appreciated.
It's a method that allows a class extending a generic class or implementing a generic interface (with a concrete type parameter) to still be used as a raw type.
Imagine this:
public class MyComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
//
}
}
This can't be used in its raw form, passing two Objects to compare, because the types are compiled in to the compare method (contrary to what would happen were it a generic type parameter T, where the type would be erased). So instead, behind the scenes, the compiler adds a "bridge method", which looks something like this (were it Java source):
public class MyComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
//
}
//THIS is a "bridge method"
public int compare(Object a, Object b) {
return compare((Integer)a, (Integer)b);
}
}
The compiler protects access to the bridge method, enforcing that explicit calls directly to it result in a compile time error. Now the class can be used in its raw form as well:
Object a = 5;
Object b = 6;
Comparator rawComp = new MyComparator();
int comp = rawComp.compare(a, b);
Why else is it needed?
In addition to adding support for explicit use of raw types (which is mainly for backwards compatability) bridge methods are also required to support type erasure. With type erasure, a method like this:
public <T> T max(List<T> list, Comparator<T> comp) {
T biggestSoFar = list.get(0);
for ( T t : list ) {
if (comp.compare(t, biggestSoFar) > 0) {
biggestSoFar = t;
}
}
return biggestSoFar;
}
is actually compiled into bytecode compatible with this:
public Object max(List list, Comparator comp) {
Object biggestSoFar = list.get(0);
for ( Object t : list ) {
if (comp.compare(t, biggestSoFar) > 0) { //IMPORTANT
biggestSoFar = t;
}
}
return biggestSoFar;
}
If the bridge method didn't exist and you passed a List<Integer> and a MyComparator to this function, the call at the line tagged IMPORTANT would fail since MyComparator would have no method called compare that takes two Objects...only one that takes two Integers.
The FAQ below is a good read.
See Also:
The Generics FAQ - What is a bridge method?
Java bridge methods explained (thanks #Bozho)
If you want to understand why you need bridge method, you better understand what happens without it. Suppose there is no bridge method.
class A<T>{
private T value;
public void set(T newVal){
value=newVal
}
}
class B extends A<String>{
public void set(String newVal){
System.out.println(newVal);
super.set(newVal);
}
}
Notice that after erasure, method set in A became public void set(Object newVal) since there is no bound on Type parameter T. There is no method in class B the signature of which is the same as set in A. So there is no override. Hence, when something like this happened:
A a=new B();
a.set("Hello World!");
Polymorphism won't work here. Remember you need to override the method of parent class in child class so that you can use parent class var to trigger polymorphism.
What bridge method does is silently override the method in parent class with all the information from a method with the same name but a different signature. With the help of the bridge method, polymorphism worked. Though on the surface, you override the parent class method with a method of different signature.
It's insteresting to note that the compiler infers that MyComparator's method:
public int compare(Integer a, Integer b) {/* code */}
is trying to override Comparator<T>'s
public int compare(T a, T b);
from the declared type Comparator<Integer>. Otherwise, MyComparator's compare would be treated by the compiler as an additional (overloading), and not overridding, method. And as such, would have no bridge method created for it.
As indicated by this article and this article, the key reason of the Java bridge method is Type Erasure and Polymorphism.
Let's take the class ArrayDeque (source code) as example, it contains a clone() method as bellow, because the class ArrayDeque implements the Cloneable interface so it must override the Object.clone() method.
public class ArrayDeque<E> extends AbstractCollection<E>
implements Deque<E>, Cloneable, Serializable
{
public ArrayDeque<E> clone() {
....
}
}
But the problem is the return type of ArrayDeque.clone() is ArrayDeque<E>, and it did not match to the method signature defined in the parent Object.clone(), and in Object.java the return type is Object instead.
public class Object {
protected native Object clone() throws CloneNotSupportedException;
}
The return type mismatch is a problem for Polymorphism. So in the compiled result file ArrayDeque.class, the Java compiler generated two clone() methods, one match the signature in the source code, the other one match to the signature in the parent class Object.clone().
clone() method returns ArrayDeque<E>, which is generated based on the corresponding source code
clone() method returns Object, which is generated based on Object.clone(). This method is doing nothing but calling the other clone() method. And, this method is tagged as ACC_BRIDGE, which indicates this method is generated by the compiler for the Bridge purpose.

Java "unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable"

I'm trying to implement a sorted list as a simple exercise in Java. To make it generic I have an add(Comparable obj) so I can use it with any class that implements the Comparable interface.
But, when I use obj.compareTo(...) anywhere in the code I get "unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable" from the compiler (with -Xlint:unchecked option). The code works just fine but I can't figure out how to get rid of that annoying message.
Any hints?
In essence, this warning says that Comparable object can't be compared to arbitrary objects. Comparable<T> is a generic interface, where type parameter T specifies the type of the object this object can be compared to.
So, in order to use Comparable<T> correctly, you need to make your sorted list generic, to express a constraint that your list stores objects that can be compared to each other, something like this:
public class SortedList<T extends Comparable<? super T>> {
public void add(T obj) { ... }
...
}
Using an interface like Comparable as a method parameter doesn't make your class generic, declaring and using generic type parameters is how you make it generic.
Quick-n-dirty answer: You are receiving the warning because you are using Comparable, which is a generic interface, as a raw type, rather than giving it a specific type arguments, like Comparable<String>.
To fix this, make add() generic by specifying type parameters:
<T extends Comparable<? super T>> add(T obj) { ... }
But this quick fix won't fix the general problem that your class is unsafe. After all, shouldn't all the objects in your list be of the same type? This add method lets you still different types into the same list. What happens when you try to compare heterogeneous types (how do you compareTo an Object instance to an Number instance, or to a String instance)? You can depend on the user of the class to do the right thing and ensure they only stick 1 kind of thing in your list, but a generic class will let the compiler enforce this rule.
The better approach: The proper fix is that your sorted list class should be probably be generic overall, just like the other collection classes in java.util.
You would probably like something like:
public class SortedList<T extends Comparable<? super T>>
implements Iterable<T> {
...
public void add(T item) { ... }
public Iterator<T> iterator() { ... }
...
}
Note that when the class is generic, the add method uses the classes formal type parameter rather than declaring its own formal type parameter.
There should be plenty of tutorials on the web on how to create a generic class, but here's a quick example:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ002
class Pair<X,Y> {
private X first;
private Y second;
public Pair(X a1, Y a2) {
first = a1;
second = a2;
}
public X getFirst() { return first; }
public Y getSecond() { return second; }
public void setFirst(X arg) { first = arg; }
public void setSecond(Y arg) { second = arg; }
}
You need to "check" or define the Comparable object like so:
add(Comparable<Object> obj)

Java Collections using wildcard

public static void main(String[] args) {
List<? extends Object> mylist = new ArrayList<Object>();
mylist.add("Java"); // compile error
}
The above code does not allow you to add elements to the list and wild cards can only be used as a signature in methods, again not for adding but only for accessing.
In this case what purpose does the above fulfil ??
Let's say you have an interface and two classes:
interface IResult {}
class AResult implements IResult {}
class BResult implements IResult {}
Then you have classes that return a list as a result:
interface ITest<T extends IResult> {
List<T> getResult();
}
class ATest implements ITest<AResult> {
// look, overridden!
List<AResult> getResult();
}
class BTest implements ITest<BResult> {
// overridden again!
List<BResult> getResult();
}
It's a good solution, when you need "covariant returns", but you return collections instead of your own objects. The big plus is that you don't have to cast objects when using ATest and BTest independently from the ITest interface. However, when using ITest interface, you cannot add anything to the list that was returned - as you cannot determine, what object types the list really contains! If it would be allowed, you would be able to add BResult to List<AResult> (returned as List<? extends T>), which doesn't make any sense.
So you have to remember this: List<? extends X> defines a list that could be easily overridden, but which is read-only.
In his book great 'Effective Java' (Second Edition) Joshua Bloch explains what he calls the producer/consumer principle for using generics. Josh's explaination should tell you why your example does not work (compile) ...
Chapter 5 (Generics) is freely available here: http://java.sun.com/docs/books/effective/generics.pdf
More information about the book (and the author) are available: http://java.sun.com/docs/books/effective/
With java generics using wildcards, you are allowed the above declaration assuming you are only going to read from it.
You aren't allowed to add/write to it, because all generic types must be stripped at compile time, and at compile time there isn't a way the compiler knows List are only strings, (it could be any object including strings!)
You are however allowed to read from it since they are going to be at least objects. Mixing different types are not allowed in java collections to keep things clean and understandable, and this helps ensure it.
The point of bounded wildcard types is their use in method signatures to increase API flexibility. If, for example, you implement a generic Stack<E>, you could provide a method to push a number of elements to the stack like so:
public void pushAll(Iterable<? extends E> elements) {
for(E element : elements){
push(e);
}
}
Compared to a pushAll(Iterable<E> elements) signature without a wildcard, this has the advantage that it allows collections of subtypes of E to be passed to the method - normally that would not be allowed because an Iterable<String> is, somewhat counterintuitively, not a subclass of Iterable<Object>.
This works:
List<? super Object> mylist = new ArrayList<Object>();
mylist.add("Java"); // no compile error
From O'Reilly's Java Generics:
The Get and Put Principle: use an extends wildcard when you only get values our of a structure, use a super wildcard when you only put values into a structure, and don't use a wildcard you both get and put.
List<? extends Object>, which is the same as List<?>, fulfills the purpose of generalizing all types List<String>, List<Number>, List<Object>, etc. (so all types with a proper type in place of the ?). Values of all of these types can be assigned to a variable of type List<?> (which is where it differs from List<Object>!).
In general, you cannot add a string to such a list. However, you can read Object from the list and you can add null to it. You can also calculate the length of the list, etc. These are operations that are guaranteed to work for each of these types.
For a good introduction to wildcards, see the paper Adding Wildcards to the Java Programming Language. It is an academic paper, but still very accessible.
Java Generics : Wild Cards in Collections
extends
super
?
Today I am going to explain you how the wild cards are useful. To understand this concept is bit difficult
Now Suppose you have abstract class and in that you have abstract method called paintObject().
Now you want to use different type of collection in every child class.
This below is AbstractMain Method.
Here Steps we have taken for this Abstract Main method
1. We have created abstract class
2. In Parameter we have define T(you can use any character)
--In this case whichever class implement this method it can used any type of class.
ex. Class can implement method like
public void paintObject(ArrayList object) or public void paintObject(HashSet object)
3. And We have also used E extends MainColorTO
-- In this case E extends MainColorTo
-- It's clearly means whichever class you want to use that must be sub class of MainColorTo
4. We have define abstract method called paintObject(T object,E objectTO)
--Now here whichever class is implement method that method can use any class on first argument and second parameter that method has to use type of MainColorTO
public abstract class AbstractMain<T,E extends MainColorTO> {
public abstract void paintObject(T Object,E TO);
}
Now we will extend above abstract class and implement method on below class
ex.
public class MainColorTO {
public void paintColor(){
System.out.println("Paint Color........");
}
}
public class RedTO extends MainColorTO {
#Override
public void paintColor() {
System.out.println("RedTO......");
}
}
public class WhiteTO extends MainColorTO {
#Override
public void paintColor() {
System.out.println("White TO......");
}
}
Now we will take two example.
1.PaintHome.java
public class PaintHome extends AbstractMain<ArrayList, RedTO> {
#Override
public void paintObject(ArrayList arrayList,RedTO red) {
System.out.println(arrayList);
}
}
Now in above PaintHome.java you can check that we have used ArrayList in first argument(As we can take any class) and in second argument we have used RedTO(Which is extending MainColorTO)
2.PaintCar.java
public class PaintCar extends AbstractMain<HashSet, WhiteTO>{
#Override
public void paintObject(HashSet Object,WhiteTO white) {
System.out.println(Object);
}
}
Now in above PaintCar.java you can check that we have used HashSet in first argument(As We Can take any class) and in second argument we have used WhiteTO(Which is extending MainColorTO)
Ponint to Remember
You can not use super keyword at class level you can only use extends keyword at class level defination
public abstract class AbstractMain<P,E super MainColorTO> {
public abstract void paintObject(P Object,E TO);
}
Above code will give you compiler error.

Categories