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>
Related
public class arr<T>
{
class comp <T extends Comparable<T>> implements Comparator<T>
{
public int compare(T lObj,T rObj)
{
return lObj.compareTo(rObj);
}
}
ArrayList<T> list;
Comparator<T> comparator;
public arr()
{
list = new ArrayList<T>();
comparator = new comp();
}
public void add(T data)
{
list.add(data);
}
public int getLength()
{
return list.size();
}
public T get(int index)
{
return list.get(index);
}
public void sort()
{
list.sort(comparator);
}
}
Hello, I am trying to make the sort function work but have a problem.
In the arr constructor, if I write
comparator = new comp<T>();
it gives me an error saying
"type argument T#1 is not within bounds of type-variable T#2 comparator =
new comp<T>(); ^
where T#1,T#2 are type-variables:
T#1 extends Object declared in class arr
T#2 extends Comparable<T#2> declared in class arr.comp"
And if I take out the type and write like this
comparator = new comp;
then it does work but gives me a warning that says
warning: [rawtypes] found raw type: arr.comp
comparator = new comp();
I can see what it means by raw types. I am not specifying the type, but somehow it works and if I try to fix the warning by specifying the type then, it throws an error. Could you please help me figure it out? I know... I am a noob my code must be a pain in your eyes. I am playing with generic comparators and trying many things to get familiar. Thank you.
Your code is confusing you, because the T defined by comp is hiding the T defined by arr. For the explanation below, I'll call them Tcomp and Tarr.
Tcomp is required to extend Comparable, but Tarr isn't required to do so, which means that Tarr cannot be "mapped" to Tcomp.
To fix, change Tarr so it is also required to extend Comparable:
public class arr<T extends Comparable<T>>
On a side note:
You comp class is an inner class, but it doesn't use anything from the outer class, so it should be a static nested class:
static class comp<T extends Comparable<T>> implements Comparator<T>
Alternatively, leave comp as an inner class, and let it reuse the T from the outer class:
class arr<T extends Comparable<T>>
{
class comp implements Comparator<T>
But, since Java (8 or higher) comes with an implementation of Comparator for comparing Comparable objects, you should use it:
public class arr<T extends Comparable<T>>
{
ArrayList<T> list;
Comparator<T> comparator;
public arr()
{
list = new ArrayList<T>();
comparator = Comparator.naturalOrder();
}
// rest of code
}
I was implementing some architecture when I saw the following error:
Error:(33, 55) java: incompatible types: inferred type does not conform to upper bound(s)
inferred: java.io.Serializable
upper bound(s): sandbox.ExpirePolicy,java.io.Serializable
The whole simplified code is below:
interface Configuration<K,V>{}
interface ExpirePolicy{}
interface Factory<T>{}
class FactoryBuilder {
public static <T extends Serializable> Factory<T> of(T instance){
System.out.println(instance.getClass());
return new Factory<T>() {};
}
}
class BaseConfiguration<K,V> implements Configuration<K,V> {
public BaseConfiguration<K,V> setExpiryPolicyFactory(Factory<? extends ExpirePolicy> factory){
return this;
}
}
class C<K,V> extends BaseConfiguration<K,V> {
public C<K,V> setExpiration(){
super.setExpiryPolicyFactory(FactoryBuilder.of((Serializable) getExpirePolicy()));
return this;
}
private ExpirePolicy getExpirePolicy(){
return new ExpirePolicy() {};
}
}
The exception is in trying to call setExpiryPolicyFactory(Factory<? extends ExpirePolicy> factory) with instance of Factory<Serializable>
But if i delete generic in extends BaseConfiguration<K,V> the program will be successfully compiled.
So the next declaration of class C is correct:
class C<K,V> extends BaseConfiguration {
public C<K,V> setExpiration(){
super.setExpiryPolicyFactory(FactoryBuilder.of((Serializable) getExpirePolicy()));
return this;
}
private ExpirePolicy getExpirePolicy(){
return new ExpirePolicy() {};
}
}
The question is: why the second implementation(of class C) will be successfully compiled and the first not?
UPD:
Simpler example of question (delete <T> from extends Base<T>) and program compiles well :
class Base<T> {
public void test(ArrayList<? extends CharSequence> list) {}
}
class Derived<T> extends Base<T> {
public void callTest() {
super.test(new ArrayList<Integer>());
}
}
When you delete <T> from extends Base<T> statement, the Base class starts to be treated as a raw type.
According to Java spec:
The supertype of a class may be a raw type. Member accesses for the
class are treated as normal, and member accesses for the supertype are
treated as for raw types. In the constructor of the class, calls to
super are treated as method calls on a raw type.
This means that super.test(...) call is also treated as method call on a raw type as if it has been declared like:
public void test(ArrayList list) {}
Thus no compilation errors happens.
It seems like the factory builder should take in an ExpirePolicy instead of Serializable for creating the factory. Changing the signature to
class FactoryBuilder {
public static <T extends ExpirePolicy> Factory<T> of(T instance){
System.out.println(instance.getClass());
return new Factory<T>() {};
}
}
enables using
class C<K,V> extends BaseConfiguration<K,V> {
public C<K,V> setExpiration(){
super.setExpiryPolicyFactory(FactoryBuilder.of(getExpirePolicy()));
return this;
}
private ExpirePolicy getExpirePolicy(){
return new ExpirePolicy() {};
}
}
without extra casts.
The second implementation of C compiles, but with warnings, because it's using raw types.
I have an interface:
public MyInterface {};
And few enums which implement MyInterface as:
public enum MyFirstEnums implements MyInterface{};
In some another class, I need a method to return Class object such that
the Class should be like MyFirstEnums, which extends enum and implements MyInterface.
The return type of method should be: <E extends Enum<?> & MyInterface>, which should allow returning MyFirstEnums.class and like enums
I tried doing it like:
public <E extends Enum<?> & MyInterface> Class<E> getClazz(){
return MyFirstEnums.class;
}
but this give me error as:
Type mismatch: cannot convert from Class<MyFirstEnums> to Class<E>
What am I missing here?
At other place, I tried a method which takes such type of class as an argument and that worked fine:
public <E extends Enum<?> MyInterface> void doSomething(Class<E> myClazz){};
//it rightly checks the type of myClazz while calling this method
You can't just return the class object of MyFirstEnum. Your method is declared to return a class object that corresponds to an enum and implements MyInterface but it could be an enum other than MyFirstEnum that also meets this criteria. Imagine you have another enum:
public enum MySecondEnum implements MyInterface { }
You could also do:
Class<MySecondEnum> clazz = getClazz();
The compiler infers the type argument from the target return type of clazz (E is inferred as MySecondEnum). In this case, clearly a runtime exception is likely to occur. For example, when you try to instantiate an object from the returned class, you would get a java.lang.InstantiationException.
Note that your method does not actually use the type argument, so why have it generic in the first place?
If you want a "generic" way to return class objects for each enum implementing the interface, you can do something like:
abstract class EnumProvider<E extends Enum<?> & MyInterface> {
...
public abstract Class<E> getClazz();
}
class MyFirstEnumProvider extends EnumProvider<MyFirstEnums> {
...
#Override
public Class<MyFirstEnums> getClazz() {
return MyFirstEnums.class;
}
}
I would try some response:
You want to define a method which return some class type which is not fully defined, but which respects: extends Enum & MyInterface.
And your Class is not passed to the method.
I have a doubt it is not possible or safe.
I would :
1 pass a Class I want as an argument
2 inverse the test: I test inside if Class< E> extends Enum & MyInterface and MyFirstEnum.class and if MyFirstEnum.class extends class< E>
3 of course Class result=MyFirstEnum.class; can be more sophisticated and not known before...
This compiles (because tests are made at runtime) but I dont know if it can help you.
public <E> Class<E> getClazz(Class< E> _return_class) throws Exception
{
Class result=MyFirstEnum.class;
if (MyInterface.class.isAssignableFrom(_return_class) )
if (Enum.class.isAssignableFrom(_return_class))
if (_return_class.isAssignableFrom(result))
return (Class<E>) result;
throw new Exception("Bad Class");
}
I have a question regarding generic types in Java. Specifically, at present, I have some code similar to this:
public interface Foo {
public <T> void bar(T[] list)
}
public class FooImpl implements Foo{
#Override
public <T extends Comparable<? super T>> void bar(T[] list) {
...
}
}
The problem is, that the compiler now complaints, that I have not implemented the bar-method in my FooImpl class.
What I want is to put some extra restriction on the generic type, specifically that they should be comparable. But I don't want to put that restriction in my Foo interface, as all implementations does not need that restriction.
Is this possible, and what should I do to fix it?
Thanks a lot in advance!
EDIT 1: Fixed typos Class --> class and Interface --> interface. But the return types are still void, not T, which is irrelevant, I suppose. My actual return type is a boolean.
EDIT 2: The actual code, as requested:
public interface SortedCriteria {
public <E> boolean isSorted(E[] list);
}
public class AscendingCriteria implements SortedCriteria {
#Override
public <E extends Comparable<? super E>> boolean isSorted(E[] list) {
int length = list.length;
for (int i = 1; i < length; i++) {
if (list[i].compareTo(list[i-1]) < 0) return false;
}
return true;
}
}
What you want to do is rejected because it would completely break polymorphism. A caller having a Foo instance could have an instance of your subclass or an instance of any other subclass. And since the interface guarantees that the method can be called with any kind of array as argument, your subclass can't break this contract by limiting the kind of array it accepts (unless it does that at runtime, by checking the type of the array and by throwing an exception, of course).
This boils down to the Liskov substitution principle, which is the basis of polymorphism and OO.
But maybe what you actually want is to make Foo a generic type:
public interface Foo<T> {
public void bar(T[] list);
}
public class FooImpl<T extends Comparable<? super T>> implements Foo<T> {
#Override
public void bar(T[] list) {
...
}
}
Consider the code:
public abstract class Item<T> implements Comparable<T>
{
protected T item;
public int compareTo(T o)
{
return 0; // this doesn't matter for the time being
}
}
public class MyItem<T> extends Item<String>
{
T object;
}
public class Foo<T>
{
protected ArrayList<T> list;
}
public class Bar<V> extends Foo<MyItem<V>>
{
public void sort()
{
Collections.sort(list);
}
}
The sort call gives the error:
Bound mismatch: The generic method sort(List< T >) of type Collections is not applicable for the arguments (ArrayList< MyItem< T > >). The inferred type MyItem< T > is not a valid substitute for the bounded parameter < T extends Comparable< ? super T > >
Why is this wrong?
If MyItem<V> implements Comparable then why is it not a substitute?
Sorry if this has been asked, but I feel the question is somewhat specific.
Actually more detailed explanation of this error gives your javac itself:
java: no suitable method found for sort(java.util.ArrayList<MyItem<V>>)
method java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<?
super T>) is not applicable (cannot instantiate from arguments because actual and formal argument lists differ in length)
method java.util.Collections.<T>sort(java.util.List<T>) is not applicable (inferred type does not conform to declared bound(s) inferred: MyItem<V> bound(s): java.lang.Comparable<? super MyItem<V>>)
So, the main question is:
why is method Collections.<T>sort(java.util.List<T>)) not applicable?
The answer is:
because in Collections.<T>sort(java.util.List<T>) method declaration there are bounds on parameter T: <T extends Comparable<? super T>>.
In another words, T must implement Comparable interface on it self. For example String class implements such interface: ...implements ... Comparable<String>.
In your case Item class doesn't implement such interface:
Item<T> implements Comparable<T> is not same thing as Item<T> implements Comparable<Item<T>>.
So, for solving this problem, your should change your Item class to this one:
public abstract class Item<T> implements Comparable<Item<T>>
{
protected T item;
public int compareTo(Item<T> o)
{
return 0; // this doesn't matter for the time being
}
}
For objects of type X to be comparable with each other, class X has to implement exactly Comparable<X>.
This is not what your code is doing, you've got a class Item<T> and you are implementing Comparable<T> instead of Comparable<Item<T>>. This means that Item<T> can be compared with T, but not with Item<T>, which is required.
Change your Item<T> class to:
public abstract class Item<T> implements Comparable<Item<T>>
{
protected T item;
#Override
public int compareTo(Item<T> o)
{
return 0; // this doesn't matter for the time being
}
}
Just change the class like follow:
public class MyItem<T> extends Item<String> implement Comparable<MyItem<T>>
{
T object;
}
Or
public abstract class Item<T> implements Comparable<MyItem<T>>
{
protected T item;
public int compareTo(MyItem<T> o)
{
return 0; // this doesn't matter for the time being
}
}
The error tips has shown us.Hope it helpful.
You do not need to have the class MyItem generified just to see the effect. The following class is enough to see what happens:
public class MyItem extends Item<String> {}
Now you have the following call:
Collections.sort(list);
As morgano stated correctly, the sort method will take a collection that is parameterized with a type T that must be comparable to T. Your MyItem class is extending Item<String>, which results in MyItem being comparable to Strings.
With a little switch in which class implements the Comparable interface, you will get the expected result:
public abstract class Item<T> {
protected T item;
}
public class MyItem extends Item<String> implements Comparable<MyItem> {
#Override
public int compareTo(MyItem o) {
return item.compareTo(o.item); // just an example
}
}
And now the call to Collections.sort(list) will work.