Eclipse tells me that Long is not Comparable - java

I am in a strange situation here, namely eclipse tells me that Long is "not a valid substitute for the bounded parameter <T extends Comparable<? super T>>". Any suggestions on what may be the cause? I'm pasting relevant code below
abstract Pair:
public abstract class Pair<T extends Comparable<? super T>, R> implements Comparable<Pair<T, R>>{
private T tt;
private R rr;
public Pair(T t, R r){
tt = t;
rr = r;
}
#Override
public String toString(){
return tt+ ": " +rr.toString();
}
}
concrete Pair:
import utilities.Pair;
public class LogBookRecord<Long, String> extends Pair<Long, String>{
LogBookRecord(Comparable t, Object r) {
super(t, r);
// TODO Auto-generated constructor stub
}
}
I tried changing abstract class header to:
public abstract class Pair<T extends Comparable<T>, R> implements Comparable<Pair<T, R>>
which did not help, and also to:
public abstract class Pair<T, R> implements Comparable<Pair<T, R>>
but then, in concrete class I get a notification which suggests that I should change type parameters to <Comparable, Object>.

public class LogBookRecord<Long, String> extends Pair<Long, String>{
^ ^
| |
generic type variable declaration (new type names) |
generic type arguments
That code is equivalent to
public class LogBookRecord<T, R> extends Pair<T, R>{
You've simply shadowed the names Long and String with your own type variable names.
Since T has no bounds, it is not necessarily Comparable and the compiler cannot validate them as type arguments to Pair.
What you want is
public class LogBookRecord extends Pair<Long, String>{
A class that is not generic, that provides concrete types as type arguments to the Pair superclass declaration.
The Java Language Specification describes the class declaration syntax.

Related

Java two-way parameterized class

Is it possible to do this in java without problems?
My IDE highlights my code as "Raw use of parameterized class 'Etat' " and "Unchecked call to 'add(E)' as a member of raw type 'java.util.ArrayList'"
My code :
public abstract class Etat<T extends Transition> {}
public abstract class Transition<E extends Etat> {}
Might you be looking for:
class Etat<E extends Etat<E, T>, T extends Transition<E, T>> {}
class Transition<E extends Etat<E, T>, T extends Transition<E, T>> {}
Then, you can do:
class MonEtat extends Etat<MonEtat, MaTransition> {}
class MaTransition extends Transition<MonEtat, MaTransition> {}
allowing the two types to know each other through their type parameter. For instance, if you declare:
class Etat<E extends Etat<E, T>, T extends Transition<E, T>> {
abstract E apply(T transition);
}
You can then be assured that
MonEtat e = ...;
e = e.apply(new MaTransition()); // compiles, and knows that MonEtat is returned

Java: Class Type mismatch

I have classes that are structured like the ones below:
interface Z {}
interface Y extends Z {}
interface X extends Y {}
private static class A<T extends Z> {}
private static class B<T extends Y> extends A<T> {}
private static class C extends B<X> {}
Why is the first one valid while the second one is not?
private Class<? extends A<? extends Z>> clazz = C.class; // valid
private Class<? extends A<? extends Z>> clazzb = B.class; // error: Type mismatch: cannot convert from Class<TEST.B> to Class<? extends TEST.A<? extends TEST.Z>>
I guess it is because the type of Y is unclear in the second example but how would you be able to clarify it?
Thank you
Java Class literal constraint
Simply said; no you can't bound the Class literal assignment as B<T> is a generic type, i.e. you can have:
Class<? extends A<? extends Z>> clazzb = B<X>.class; // illegal statement
// OR
Class<? extends A<? extends Z>> clazzb = B<W>.class; // assuming W is a sub-type of X
as there is only one class literal (in terms of byte code (runtime) and in terms of language constraints (compile-time)): B.class
And since the compiler won't be able to know of which type the type parameter T would be for the B class, it won't allow such an assignment.
Legal assignment
Below assignment statement would be legal (compiles fine):
Class<? extends A> clazzb = B.class;
but with warnings and that would perfectly complies with the Generic Class and Type Parameters Java Language Specification.
I've seen many times a Java specific-pattern where developers work-around the compiler type-check with a generic utility method inferring its return type to match the assigned reference type:
<!-- language : lang-java -->
#SuppressWarnings("unchecked")
public static <T> Class<T> inferType(Class<?> clazz) {
return (Class<T>) clazz;
}
Then you would be able to perform what used to be forbidden:
Class<? extends A<? extends Z>> clazzb = generify(B.class);
Note that this should be nothing but a non-recommended workaround. Just to let you be more sure, here down a quite confusing statement that compiles just fine:
Class<C> clazzb = generify(A.class);
At first glance, that should not work, but it will as you are assigning a class literal to a class reference after all.

The generic type upper bound to be generic itself

I'm creating a generic interface and its class implementation. It's a disjoint set. The generic type upper boundary for this class is generic itself:
public class MyDisjointSet<K extends Pair<T, T>> implements IMyDisjointSet<K> {
}
and
public interface IMyDisjointSet<T> {}
but I get compile error Cannot resolve symbol T.
When I add a second parameter to the list of generic types it works compiles:
public class MyDisjointSet<K extends Pair<T, T>, T> implements IMyDisjointSet<K>
Why should we put T here? why not before class name?
Please try
public class MyDisjointSet<K extends Pair<T, T>,T> implements IMyDisjointSet<K> {

Implementing Comparable with a generic class

I want to define a class that implements the generic Comparable interface. While in my class I also defined a generic type element T. In order to implement the interface, I delegate the comparison to T. Here is my code:
public class Item<T extends Comparable<T>> implements Comparable<Item> {
private int s;
private T t;
public T getT() {
return t;
}
#Override
public int compareTo(Item o) {
return getT().compareTo(o.getT());
}
}
When I try to compile it, I get the following error information:
Item.java:11: error: method compareTo in interface Comparable<T#2> cannot be applied to given types;
return getT().compareTo(o.getT());
^
required: T#1
found: Comparable
reason: actual argument Comparable cannot be converted to T#1 by method invocation conversion
where T#1,T#2 are type-variables:
T#1 extends Comparable<T#1> declared in class Item
T#2 extends Object declared in interface Comparable
1 error
Can anybody tell me why and how to fix it?
Item (without any type argument) is a raw type, so:
We could pass any kind of Item to Item.compareTo. For example, this would compile:
new Item<String>().compareTo(new Item<Integer>())
The method o.getT() returns Comparable instead of T, which causes the compilation error.
In the example under the 1st point, after passing Item<Integer> to Item.compareTo, we would then erroneously pass an Integer to String.compareTo. The compilation error prevents us from writing the code which does that.
I think you just need to remove the raw types:
public class Item<T extends Comparable<T>>
implements Comparable<Item<T>> {
...
#Override
public int compareTo(Item<T> o) {
return getT().compareTo(o.getT());
}
}
You're using raw types in your class definition (Item<T> is generic, but you're omitting the type parameter <T>), change it to:
class Item<T extends Comparable<T>> implements Comparable<Item<T>>
(Note the last <T>)
The compareTo method will then have to be changed as well:
public int compareTo(Item<T> o) { // again, use generics
return getT().compareTo(o.getT());
}
I think, this makes more sense. I have compiled and tested the following :
class Item<E extends Comparable<E>> implements Comparable<E> {
private int s;
private E t;
public E getE() {
return t;
}
#Override
public int compareTo(E e) {
return getE().compareTo(e);
}
public int compareTo(Item<E> other)
{
return getE().compareTo(other.getE());
}
}
Notice that you now need to have two compareTo methods.
A bit of a related issue that I ran into, and couldn't find a concrete answer.
Suppose you have an interface
public interface myInt extends Comparable<myInt>
And a class MyClass that implements myInt.
Now you only want to compare MyClass with MyClass objects. How should we rewrite the interface and the class?
Answer:
public interface myInt<T extends myInt<T>> extends Comparable<T>
public class MyClass implements myInt<MyClass>

Overriding method with generic return type

Let's say I have a super-class that defines the following abstract method
public abstract <T extends Interface> Class<T> getMainClass();
Now if I want to override it in some sub-class
public Class<Implementation> getMainClass(){
return Implementation.class;
}
I get a warning about type safety and unchecked conversion:
Type safety: The return type Class<Implementation> for getMainClass() from the type SubFoo needs unchecked conversion to conform to Class<Interface> from the type SuperFoo
Doesn't Class<Implementation> fall under Class<T> if <T extends Interface>? Is there any way to properly get rid of the warning?
the overriding method's return type must be a subtype of the overridden method's return type.
Class<Impl> is not a subtype of Class<T> where <T extends Interface>. T is unknown here.
Class<Impl> is a subtype of Class<? extends Interface>, per subtyping rules.
some subtyping rules regarding wildcards:
for any type X
A<X> is a subtype of A<? extends X>
A<X> is a subtype of A<? super X>
if S is subtype of T
A<? extends S> is a subtype of A<? extends T>
A<? super T> is a subtype of A<? super S>
More concisely, ( <: means "is a subtype of" )
A<S> <: A<? extends S> <: A<? extends T>
A<T> <: A<? super T> <: A<? super S>
Consider the following scenario similar to yours:
public class SuperFoo {
public abstract <T extends Interface> List<T> getList();
}
public class SubFoo extends SuperFoo {
private List<Implementation> l = new ArrayList<Implementation>();
public List<Implementation> getList() {
return l;
}
public void iterate() {
for (Implementation i: l) ...;
}
}
SubFoo subFoo = new SubFoo();
SuperFoo superFoo = subFoo;
superFoo.getList().add(new AnotherImplementation()); // Valid operation!
subFoo.iterate(); // Unexpected ClassCastException!
In this case unchecked conversion warning warns you about possibility of unexpected ClassCastException.
However, in your case, when return type is Class<...>, it's not a problem (as far as I understand), so you can legally suppress a warning:
#SuppressWarnings("unchecked")
public Class<Implementation> getMainClass(){ ... }
Another option is to make SuperFoo itself generic:
public class SuperFoo<T extends Interface> {
public abstract Class<T> getMainClass();
}
public class SubFoo extends SuperFoo<Implementation> {
public Class<Implementation> getMainClass() { ... }
}
For yet another (and perhaps the best) option see Stas Kurilin's answer.
try this
public abstract Class<? extends Interface> getMainClass();
reorganized example
by such warnings java tried prevents cases like this
class OtherImpl implements Interface{
}
A a = new B();//where A - your abstract class and B - implementation
Class<OtherImpl> other = a.<OtherImpl>getMainClass();//some broken think, But _without_ runtime exception
As #axtavt mentioned example was broken. I reorganized it.
Why do you want to have something like public abstract Class<? extends Interface> getMainClass(); rather than public abstract Interface getMainClass();?
I think you can simply return an instance of Interface, and then, if the caller wants to have access to the underlying runtime class can simply call getClass() on the returned object.
Essentially, I think you can simply do
public InterfaceImpl implements Interface {
// ...
};
public abstract class A {
public abstract Interface getMainClass();
// ...
}
public class AImpl {
return new InterfaceImpl();
}
public class Main {
public static void main(String[] args) {
AImpl aImpl = new AImpl();
Interface i = aImpl.getMainClass();
System.out.println(i.getClass());
}
}

Categories

Resources