How to use Comparable interface with generic static method?
Suppose lets say I have:
**public static <T extends Comparable<T>>int larger(T[] array,T element)**
Why should I extend an Interface with T here instead of using implements?
Please Help me out.Thanks.
According to Java generics, you should use extends even to interfaces, there's no such thing as impelements in bounded types.
Related
Given an interface I:
interface I<T> {
public abstract T doSomthing(T other);
}
where any class C which implements the interface I will always use itself (C) as the type parameter:
class MyClass implements I<MyClass> {
#Override
public MyClass doSomthing(MyClass other) {
return null;
}
}
Is there a way to accomplish this without explicitly passing the class C as the parameter every time a new class implements the interface?
In other words is it possible, in an interface, to reference the class which implements that interface?
tl;dr
You asked:
Is there a way to accomplish this without explicitly passing the class C
No, not in Java.
Example
You seem to be describing exactly the scenario of the Comparable<T> interface bundled with Java. That interface has a single generic argument, for the type of the two objects to be compared. That interface requires a single method compareTo(T o) taking a single parameter of that same generic type.
Let’s look at an example usage in the OpenJDK source code, the source code for class Year.
The class declares itself explicitly as the type of comparison on the Comparable interface being implemented.
public final class Year
implements Temporal, TemporalAdjuster, Comparable<Year>, Serializable {
The compareTo method explicitly cites its own class as the type being compared.
#Override
public int compareTo(Year other) {
return year - other.year;
}
You asked:
Is there a way to accomplish this without explicitly passing the class C as the parameter every time a new class implements the interface?
It seems the answer is No. The implementing class must cite itself explicitly as the fulfillment of the generic type of the interface being implemented.
Caveat: (a) I am not an expert on such language matters. (b) I may have misunderstood your question.
To add to the other answer: what you're describing is a self type.
Some other languages have it (such as Scala).
But I'm afraid Kotlin doesn't. (Java doesn't, either.)
There has been long discussion about the possibility of adding it to a future version of Kotlin; it seems the potential uses may not be wide enough for it to be worthwhile, though there doesn't seem to be a final consensus.
The usual workaround is using a type parameter — similar to what C++ calls the curiously-recurring template pattern. It's not quite as typesafe in Java or Kotlin, as this question illustrates, but covers most of the same ground.
That's called self-bounded generics. It could be declared in Java as well as in Kotlin.
Java:
interface I<T extends I<T>> {
public abstract T doSomething(T other);
}
Kotlin:
interface I<T : I<T>> {
fun doSomething(other: T): T
}
But it doesn't mean, that generic parameter could be omitted then you declare classes, implementing this interface. It just imposes additional restrictions on type, you're passing as a generic parameter (narrowing it down to only one type). Type inference is not supported for class declaration neither in Kotlin, nor in Java.
Also see: Can I resolve a generic type from another generic declaration in an interface?
I've been reading "Java. A Beginner's Guide" by Herbert Schildt. In the section on generic interfaces on one page the author writes (emphasis mine):
Any class that implements a generic interface must itself be generic.
And on the next page (emphasis mine):
In general, if a class implements a generic interface, then that class must also be generic, at least to the extent that it takes a type parameter that is passed to the interface.
So are there any specific situations where a non-generic class can implement a generic interface in Java? Or all such classes are generic in that they 'inherit' that generality from the generic interface?
UPD: I should have read the section further. The author goes on to state:
Of course, if a class implements a specific type of generic interface, such as shown here:
class MyClass implements Containment<Double> {
then the implementing class does not need to be generic.
This is, I believe, the gist of all the answers to my post.
It is possible to create a non-generic class that implements a generic interface, provided that the type parameters are provided.
A relatively simplistic example:
public class LocalDateParser implements Function<String, LocalDate> {
public LocalDate apply (String s) {
return LocalDate.parse(s);
}
}
Of course, you can only assign an instance of this class to Function<String, LocalDate>, and not to any other Function<T, R>.
I think the author is plain wrong in both statements. A generic class is a class that accepts a generic type parameter. And you can create a class that doesn't accept any generic type parameter that implements a generic interface:
public class CaseInsensitiveComparator implements Comparator<String> {
#Override
public int compare(String s1, String s2) {
return s1.compareToIgnoreCase(s2);
}
}
In fact, this class already exists in the JDK, though it's implemented differently. Please see String.CASE_INSENSITIVE_ORDER for further details.
The guide you're reading is wrong.
There are many examples of non-generic classes implementing generic interfaces.
The most common one is Comparable<T>. The Java 8 javadoc lists 152 implementing classes, few of which pass on a generic type argument to the interface, since they are all supposed to specify themselves as the argument to Comparable, e.g.
public final class String implements Serializable, Comparable<String>, CharSequence
public final class Integer extends Number implements Comparable<Integer>
public final class Instant implements Temporal, TemporalAdjuster, Comparable<Instant>, Serializable
how do I correctly write following class declaration in Java?
public class BinarySearchTree<T extends BinarySearchNode<E implements Comparable<E>>> implements Iterable<E>
Basically, I am trying to create a BinarySearchTree of any class T that inherits BinarySearchNode of a Comparable datatype E (And my BinarySearchTree should also be Iterable).
How can I properly declare that class in Java?
Thanks!
public class BinarySearchTree<T extends BinarySearchNode<E>, E extends Comparable<E>> implements Iterable<E>
The type parameter E needs to be defined separately from the node type, even if it ends up looking redundant: BinarySearchTree<BinarySearchNode<String>, String>. Java won't let you directly access a generic parameter of a generic type.
Also, note that generic parameters always use "extends" even with interfaces.
With Generics in Java, you will only use extends. So, essentially your method decoration would become:
public class BinarySearchTree<T extends BinarySearchNode<E extends Comparable<E>>> extends Iterable<T>
Even for those classes that implement an interface, generics will use extends. The only other syntax for generics is super if you are looking at the inheritance from the opposite direction
I'm writing a generic function in java, however, I can't seem to tell if there's any way of setting a list of classes that a Generic Object must be in.
Something like this:
public static <T in {String.class, Integer.class, Long.class}> Collection<T> test(Collection<T> val);
You can have Bounded Type Parameters like this for example:
public static <T extends String & Runnable> Collection<T> test(Collection<T> val);
But your example will not work since you have several classes and Java does not support Multiple inheritance.
Also, your examples String, Integer and Long are final so they will not possible to extend anyway.
No. You can't do that in java.
What you desire is an "OR" bound. Java allows "AND" bounding, eg:
List<T extends Runnable & Comparable<T>>
But the analogous "OR" is not supported:
List<T extends Integer | String> // doesn't compile
When you think about it, it doesn't make any sense. Use separate classes/methods for each type bound.
Unfortunately you can't do what you're trying to do in Java - if it allowed you to specify a generic from a list, you'd be able to write a function which operated either on Integers or ArrayLists, which makes no sense as they don't share common functionality. If you want to limit your method to certain types, either find a base class/interface which they all inherit from supporting the functionality you need (public static <T extends BaseClass> Collection<T> test(Collection<T> val);) or write a set of oveloaded methods, one for each type you want to support.
Well you can and can not at the same time.
In your specific example it is impossible.
But such an example would work:
public <T extends CharSequence & Comparable & Closeable> void go(){
For your case I would go with:
public <T extends Number & CharSequence> void go() // same rule applies as extend a class and implement as many interfaces as you want
You cannot do that. Generics is only for enforcing type safety (guaranteeing that the type can perform a particular method, etc.). There is no type-safety requirement that correspond to such an "OR" bound. Requirements on type safety only require an "AND" bound.
I wanted to do something along the lines of:
public class MyClass<T implements Comparable> {
....
}
But I can't, since, apparently, generics only accept restrictions with subclasses, and not interfaces.
It's important that I'm able to compare the types inside the class, so how should I go about doing this? Ideally I'd be able to keep the type safety of Generics and not have to convert the T's to Object as well, or just not write a lot of code overall. In other words, the simplest the better.
The implements is wrong. It only accepts extends or super. You can use here extends:
public class MyClass<T extends Comparable<T>> {
// ...
}
To learn more about Generics, you may find this tutorial (PDF) useful.
The best way to do it is:
public class MyClass<T extends Comparable<? super T>> {
....
}
If you just do <T extends Comparable<T>>, then it won't work for subclasses of comparable classes.
Also for interfaces you have to use extends. So in your case it would be:
public class MyClass<T extends Comparable<T>> {
....
}