I am new to java. I am just trying to pass Comparable<String> into a method parameter of generic type <E extends Comparable<E>> . I believe the meaning of <E extends Comparable<E>> is any object that extends Comparable. Please let me know how to pass Comparable<String> or any object that extends Comparable<String> and has an other object in it.
Compiler is giving me error The inferred type Compare<String> is not a valid substitute for the bounded parameter <E extends Comparable<E>>
Code:
public class Compare<T> implements Comparable<T>{
public int compareTo(T o) {
return 0; // Not worried about logic
}
}
class CompareTest{
public <E extends Comparable<E>>void testGeneric(E e){
System.out.println("Executed");
}
public static void main(String args[]){
Compare<String> compare = new Compare<String>();
CompareTest test = new CompareTest();
test.testGeneric(compare);
//The inferred type Compare<String> is not a valid substitute for the bounded
//parameter <E extends Comparable<E>>
}
}
E extends Comparable<E> means: a type E that is able to compare to other objects of the same type E.
But your Compare type doesn't qualify. It can't compare with another Compare. A Compare<T> can only compare itself to a T, and not to a Compare<T>, since it's declared as
public class Compare<T> implements Comparable<T>
It's quite hard to understand what you want to achieve with this Compare type.
Your method
public <E extends Comparable<E>> void testGeneric(E e){
expects a type E that is a sub type of Comparable<E>. But you are passing it a Compare<String> which is not a sub type of <Comparable<Compare<String>>, but a sub type of Comparable<String>.
You'll have to clarify what you are trying to do if you need more help.
The error in my IDE says:
Inferred type 'Compare<java.lang.String>' for type parameter 'E' is not within its bound;
should implement 'java.lang.Comparable<Compare<java.lang.String>>'
It seems that E is inferred as Compare<String> instead of String. To get E to be String, try this:
public <E extends Comparable<E>> void testGeneric(Comparable<E> e){
To define a class as being comparable, the generic parameter to Comparable must be the class itself:
public class MyComparable implements Comparable<MyComparable> {
public int compareTo(MyComparable o) {
return 0;
}
}
Applying that to your class, you get the following code (which compiles):
public static class Compare<T> implements Comparable<Compare<T>> {
public int compareTo(Compare<T> o) {
return 0; // Not worried about logic
}
}
class CompareTest {
public <E extends Comparable<E>> void testGeneric(E e) {
System.out.println("Executed");
}
}
public static void main(String[] args) {
Compare<String> compare = new Compare<String>();
CompareTest test = new CompareTest();
test.testGeneric(compare);
}
Related
I am struggling with creating generic data types that require that its element to be comparable.
I have attempted to construct what I think is the most basic implementation of this, and it still is not working.
public class GenericPair<T> {
T thing1;
T thing2;
public GenericPair(T thing1, T thing2){
this.thing1 = thing1;
this.thing2 = thing2;
}
public <T extends Comparable<T>> int isSorted(){
return thing1.compareTo(thing2);
}
public static void main(String[] args){
GenericPair<Integer> onetwo = new GenericPair<Integer>(1, 2);
System.out.println(onetwo.isSorted());
}
}
My understanding is that > requires that whatever type T ends up, it must implement comparable and therefore must have a compareTo() function. In this case Integers should have this functionality right?
I am getting the error:
GenericPair.java:15: error: cannot find symbol
return thing1.compareTo(thing2);
^
symbol: method compareTo(T)
location: variable thing1 of type T
where T is a type-variable:
T extends Object declared in class GenericPair
What is going on here?
public <T extends Comparable<T>> int isSorted(){
return thing1.compareTo(thing2);
}
This new T is hiding the type parameter of your class (also called T). They are two different types! And thing1 and thing2 are instances of your class's generic type, which aren't necessarily comparable.
So, you should declare your class's type parameter to be comparable instead:
class GenericPair<T extends Comparable<T>>
And now:
public int isSorted(){
return thing1.compareTo(thing2); // thing1 and thing2 are comparable now
}
The problem is that generic T for the whole class doesn't know a compareTo method. Even if you declare <T extends Comparable<T>> for this single method, you're just creating a new T that hides the definition of the generic T from the class.
A solution may be declaring T extends Comparable<T> in the class itself:
class GenericPair<T extends Comparable<T>> {
public int isSorted() {
return thing1.compareTo(thing2);
}
}
public <T extends Comparable<T>> int isSorted(){
return thing1.compareTo(thing2);
}
You can't have a method that imposes new constraints on the generic type parameter defined by the class. You would have to declare
public class GenericPair<T extends Comparable<T>> {
public int isSorted() {
return thing1.compareTo(thing2);
}
}
Suppose I have a java class
public class Foo<ELEMENT, COMPARATOR extends Comparator<ELEMENT>> {
public Foo(ELEMENT e, COMPARATOR c) {...}
}
How can I reload the type parameter <ELEMENT> so that I can also have something like
public class Foo<ELEMENT extends Comparable> {
public Foo(ELEMENT e) {
this(e, new Comparator<ELEMENT>() {
public int compare(ELEMENT e1, ELEMENT e2) {
return e1.compareTo(e2);
}
})
}
}
You can't, basically. (TreeSet is an example of a class that would do it if it could.)
One thing you can do, on the other hand, is use static factory methods instead of public constructors. For example, you can write
public class Foo<E> {
public static <E> Foo<E> withComparator(E e, Comparator<? super E> comparator){
...
}
public static <E extends Comparable> Foo<E> withoutComparator(E e) {
...
}
}
This allows you to put different type constraints on different factory methods, e.g. adding a Comparable constraint on the overload that doesn't take a Comparator.
I am with a sort of trouble when using java generics in the visitor pattern.
My code is something like that:
public interface MyInterfaceVisitor<A, B> {
public A visitMyConcreteObject(MyConcreteObject object, B parameter);
}
public interface MyObject {
public <A, B> A accept(MyInterfaceVisitor<A, B> visitor, B parameter);
}
public class MyConcreteObject implements MyObject {
#Override
public <A, B> A accept(MyInterfaceVisitor<A, B> visitor, B parameter) {
return visitor.visitMyConcreteObject(this, parameter);
}
}
public class MyConcreteVisitor implements MyInterfaceVisitor<????> {
#Override
public <X extends C> X visitMyConcreteObject(MyConcreteObject object, Class<X> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
// This method is the entry point of the MyConcreteVisitor.
public <X extends C> void someOtherMethod(Class<X> parameter) {
MyObject m = ...;
X x = m.accept(this, parameter);
...;
}
}
public class C {}
public class Dog extends C {}
public class Cat extends C {}
public class Client {
public static void main(String... args) {
MyConcreteVisitor v = new MyConcreteVisitor();
v.someOtherMethod(Cat.class);
v.someOtherMethod(Dog.class);
}
}
// We have other implementations of the visitor that does not matters, like this one.
public class SomeOtherConcreteVisitor implements MyInterfaceVisitor<String, Integer> {
#Override
public String visitMyConcreteObject(MyConcreteObject object, Integer parameter) {
return "foo";
}
}
I need to find what is the generic signature in the ???? that makes the code compilable allowing the overriden method in MyConcreteVisitor class to match the signature in MyInterfaceVisitor interface.
I can't change the signature of the visitMyObject in the MyInterfaceVisitor interface, nor its generics. This happens because others implementations of MyInterfaceVisitor exists and their generics have nothing to with the ones from MyConcreteVisitor.
The MyConcreteVisitor class should not have a generic per-se, so the compiler must allow a MyConcreteVisitor v = new MyConcreteVisitor(); without generating the unchecked or rawtypes warning.
If I change the concrete visitMyObject to public C visitMyObject(MyObject object, Class<? extends C> parameter) and declare the ???? as <C, Class<? extends C>>, I would need to add a cast in the someOtherMethod.
How to define the generic type making it compilable without getting the unchecked or rawtypes warning, changing the interface or adding a cast? Is this even possible in java or I am abusing the generics too much?
The issue is that your implementation is trying to introduce another type parameter X extends C to the method visitMyConcreteObject and resolve the B parameter with it. You can't make visitMyConcreteObject generic with X but try to resolve B with a type parameterized by X, e.g. Class<X>, because B is resolved at the class declaration but X is only declared by a method of the class.
From what I can see, you have two options. Either make MyConcreteVisitor generic on X:
public class MyConcreteVisitor<X extends C> implements MyInterfaceVisitor<X, Class<X>> {
#Override
public X visitMyConcreteObject(MyConcreteObject object, Class<X> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
}
Or get rid of X and lose type safety (beyond the concrete type C):
public class MyConcreteVisitor implements MyInterfaceVisitor<C, Class<? extends C>> {
#Override
public C visitMyConcreteObject(MyConcreteObject object, Class<? extends C> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
}
i think this is what you are looking for:
public class MyConcreteVisitor implements MyInterfaceVisitor<Object,Class<?>> {
#Override
public Object visitMyConcreteObject(MyConcreteObject object, Class<?> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
// This method is the entry point of the MyConcreteVisitor.
public <X> void someOtherMethod(Class<X> parameter) {
MyObject m = ...;
X x = parameter.cast(m.accept(this, parameter));
...;
}
}
I tried to create an interface ISortableStack using <E extends comparable <E>> but I can't move forward. What does the following do?
<E extends Comparable<E>>
I've tried this, but it doesn't help.
<E extends Comparable<E>> means that E must be a type that knows how to compare to itself, hence, the recursive type definition.
public class Comparables {
static class User implements Comparable<User> {
#Override
public int compareTo(User user) {
return 0;
}
}
/**
* This class cannot be used with Collections.sort because an
* UncomparableUser is not comparable with itself. However, notice
* that you get no compiler error just for implementing
* Comparable<String>.
*/
static class UncomparableUser implements Comparable<String> {
#Override
public int compareTo(String user) {
return 0;
}
}
public static void main(String[] args) {
List<User> users = Arrays.asList(new User());
// Using this would cause a compiler error
// List<UncomparableUser> users = Arrays.asList(new UncomparableUser());
Collections.sort(users);
}
}
If you're asking what does this mean:
<E extends Comparable<E>>
It means that the class 'E' passed in must implement the Comparable interface.
The < and > characters are part of the "generic" syntax. The standard library is choke full of "generic" interfaces; take a look at the Set interface for an example.
I want to have an interface A parameterised by T A<T>, and also want every class that implements it to also implement Comparable (with T and its subtypes). It would seem natural to write interface A<T> extends Comparable<? extends T>, but that doesn't work. How should I do it then?
When Comparable<? extends T> appears it means you have an instance of Comparable that can be compared to one (unknown) subtype of T, not that it can be compared to any subtype of T.
But you don't need that, because a Comparable<T> can compare itself to any subtype of T anyway, e.g. a Comparable<Number> can compare itself to a Comparable<Double>.
So try:
interface A<T> extends Comparable<T> {
// ...
}
or
interface A<T extends Comparable<T>> extends Comparable<A<T>> {
// ...
}
depending on whether you need to be able to compare instances of T in order to implement your compareTo method.
If you use comparable you do not need to specify the possibility for subtypes in the compare function, it is by nature possible to pass in any subtype of an object X into a method that declared a parameter of class X. See the code below for more information.
public interface Test<T> extends Comparable<T> {
}
class TestImpl implements Test<Number> {
#Override
public int compareTo(final Number other) {
return other.intValue() - 128;
}
}
class TestMain {
public static void main(final String[] args) {
TestImpl testImpl = new TestImpl();
testImpl.compareTo(Integer.MIN_VALUE);
}
}