Understanding bounded generics in java. What is the point? - java

I am trying to understand bounded types and not quite grasping the point of them.
There is an example of bounded generics on which provides this use case:
public class NaturalNumber<T extends Integer> {
private T n;
public NaturalNumber(T n) { this.n = n; }
public boolean isEven() {
return n.intValue() % 2 == 0;
}
// ...
}
If you are going to restrict the classes that can be the parameterized type, why not just forget the parameterization all together and have:
public class NaturalNumber {
private Integer n;
public NaturalNumber(Integer n) { this.n = n; }
public boolean isEven() {
return n.intValue() % 2 == 0;
}
// ...
}
Then any class that extends/implements Integer can be used with this class.
Also, a side question: How is T extending Integer in the first example when the Java Integer class is final?

How is T extending Integer in the first example when the Java Integer class is final?
T can only be Integer, so the "extends" here is purely symbolic. (I'm starting with the side-note because, indeed, it's an example where generics are useless. I truly have no idea why the tutorial thinks this is an informative demonstration. It's not.)
Suppose instead that T extends Number:
class Example<T extends Number> {
private T num;
void setNum(T num) { this.num = num; }
T getNum() { return num; }
}
So the point of generics in general, is that you can do this:
Example<Integer> e = new Example<>();
e.setNum( Integer.valueOf(10) );
// returning num as Integer
Integer i = e.getNum();
// and this won't compile
e.setNum( Double.valueOf(10.0) );
Generics are a form of parametric polymorphism, essentially it lets us reuse code with a generality regarding the types involved.
So what's the point of a bound?
A bound here means that T must be Number or a subclass of Number, so we can call the methods of Number on an instance of T. Number is unfortunately a generally useless base class on its own (because of precision concerns), but it might let us do something interesting like:
class Example<T extends Number> extends Number {
// ^^^^^^^^^^^^^^
...
#Override
public int intValue() {
return num.intValue();
}
// and so on
}
It's more common, for example, to find T extends Comparable<T> which lets us do something more meaningful with T. We might have something like:
// T must be a subclass of Number
// AND implement Comparable
Example<T extends Number & Comparable<T>>
implements Comparable<Example<T>> {
...
#Override
public int compareTo(Example<T> that) {
return this.num.compareTo(that.num);
}
}
And now our Example class has a natural ordering. We can sort it, even though we have no idea what T actually is inside the class body.
If we combine these concepts, that:
generics allow the "outside world" to specify an actual type and
bounds allow the "inside world" to use a commonality,
we could build constructs such as:
static <T extends Comparable<T>> T min(T a, T b) {
return (a.compareTo(b) < 0) ? a : b;
}
{
// returns "x"
String s = min("x", "z");
// returns -1
Integer i = min(1, -1);
}

Related

Java Generics - Comparable interface

In the code below Comparable interface is used to ensure x and y should be of same reference type but as V is extending T so V should be of the same type as T or subclass of T then what is the point of using Comparable interface.
Also if I am not using Comparable interface then the last call to isIf method is getting compile despite x and y are of different types.
Can anyone explain the use Comparable interface regarding this program?
public class Generics_13 {
static <T extends Comparable<T>, V extends T> boolean isIn(T x, V[] y) {
for(int i = 0;i < y.length;i++)
if(x.equals(y[i])) return true;
return false;
}
public static void main(String[] args) {
Integer nums[] = {10, 20, 30};
if(isIn(10, nums))
System.out.println("10 belongs to the array");
if(!isIn(60, nums))
System.out.println("70 doesnt belong to the array");
String arr[] = {"Neeraj", "Parth", "Ritum"};
if(!isIn("abc", arr))
System.out.println("abc doesnt belongs to the array");
/*if(isIn("String", nums)) // illegal
System.out.println("This wont compile");
*/
}
}
The current use of generics doesn't really makes sense, because no method from Comparable is ever used, which means that you could simply remove the extends declaration.
Also the Type V is also not used, as you can simply replace it by T and not break your logic. so the final result would look like this:
public class Generics_13 {
static <T> boolean isIn(T x, T[] y) {
for(int i = 0;i < y.length;i++)
if(x.equals(y[i])) return true;
return false;
}
// main() etc follow here
}
But now that we have the Stream API in java-8 you can use the following snippet to achieve the same thing:
static <T> boolean isIn(T x, T[] y) {
return Arrays.stream(y).anyMatch(i -> i.equals(x));
}
The comparable here in your scenario is optional.
T extends Comparable<T>
What this means is that whatever value you are passing should implement the interface comparable.
which basically means that the type parameter can be compared with other instances of the same type.
Now you might be wondering that since you are passing primitive data types, then how does the code not throw an error?
The reason for this is that the primitives are autoboxed to wrapper objects which implement Comparable.
So your ints become Integer and String is already an object both of which implement Comparable.
PS : your code will also work for objects provided that the class implements comparable

Bounding type parameters of generic methods with interfaces?

So I have 2 versions of the same method.
Version 1:
public static <T> int countGreaterThan(T[] anArray, T elem)
{
int count = 0;
for (T e : anArray)
{
if (e > elem)
count++;
}
return count;
}
Version 2:
public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem)
{
int count = 0;
for (T e : anArray)
{
if (e.compareTo(elem) > 0)
count++;
}
return count;
}
Eclipse complains about Version 1 because the > operator can only be used when comparing primitives, which makes sense to me.
So to fix this problem, the internet tells me to use a type parameter bounded by the Comparable interface. This is where I start to lose grasp of what's going on...
From my basic understanding of interfaces, a class that implements an interface must provide a method body for each of the methods declared in the interface.
Thus, why doesn't Version 2 have to look like this?
public int compareTo(T o)
{
//stuff for method body
}
public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem)
{
int count = 0;
for (T e : anArray)
{
if (e.compareTo(elem) > 0)
count++;
}
return count;
}
^I get that this isn't correct syntax, but I just did it to illustrate my question as to why I don't have to write a method body for the method in the Comparable interface in this situation.
Please try to keep the explanation in Layman's terms. I've been teaching myself this stuff, so simple explanations help me understand the more technical side of topics when I research them further.
Sorry for the confusion, let me clarify.
Here is the code for the Comparable interface:
public interface Comparable<T> {
public int compareTo(T o);
}
There is no method body for compareTo() because it's an interface. Why don't I have to manually write a body for compareTO() so I can use the interface in my countGreaterThan() method?
Is it because the interface is part of the Java Collections Framework (if that's why please explain how that works)
Here's a different situation where I create my own interface:
public interface Dance { //an interface
public void boogie(int count);
}
and in order to implement that interface in different classes I need to write method bodies in those classes for the method in the dance interface.
public class theMoonwalk implements Dance {
public void boogie(int count) {
System.out.println("Slide " + count + " times!");
}
public void mJ() {
System.out.println("Michael Jackson did this dance!");
}
public class theHustle implements Dance {
public void boogie(int steps) {
System.out.println("Step " + steps + " times!");
}
}
public class theJitterBug implements Dance {
public void boogie(int twists) {
System.out.println("Twist " + twists + " times!");
}
}
Why don't I have to write a method body for compareTo() (because a method body is not included in the Comparable interface for compareTo() )?
The type that T ultimately refers to has to implement Comparable<T>, not the class that you're declaring the type bound on.
To make it a bit simpler: in order to use your countGreaterThan method, whatever objects are contained in your array and in your elem argument must be a Comparable object.
This means that an invocation like this is acceptable:
Integer[] foo = {1, 2, 3, 4, 5};
YourClass.countGreaterThan(foo, 2);
Your type is bound to Integer, and Integer implements Comparable<Integer>.
This is not acceptable:
Object[] bar = {new Object(), new Object(), new Object()};
YourClass.countGreaterThan(bar, new Object());
Your type is bound to Object, and Object does not implement Comparable. The same logic applies to a custom object that you implement; if it isn't bound to Comparable, then it's not going to be in the proper bound.

Generics in Method Level Java [duplicate]

I am trying to create a generic class in Java that will perform operations on numbers. In the following example, addition, as follows:
public class Example <T extends Number> {
public T add(T a, T b){
return a + b;
}
}
Forgive my naivety as I am relatively new to Java Generics. This code fails to compile with the error:
The operator + is undefined for the argument type(s) T, T
I thought that with the addition of "extends Number" the code would compile. Is it possible to do this Java or will I have to create overridden methods for each Number type?
Number does not have a + operator associated with it, nor can it since there is no operator overloading.
It would be nice though.
Basically, you are asking java to autobox a descedant of Number which happens to include Integer, Float and Double, that could be autoboxed and have a plus operator applied, however, there could be any number of other unknown descendants of Number that cannot be autoboxed, and this cannot be known until runtime. (Damn erasure)
Your problem is not really related to generics, rather to operators, primitives vs objects, and autoboxing.
Think about this:
public static void main(String[] args) {
Number a = new Integer(2);
Number b = new Integer(3);
Number c = a + b;
}
The above does not compile
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(3);
Number c = a + b;
}
The above does compile, but only because of autoboxing - which is kind of a hacky syntax glue introduced in Java 5, and only works (in compile time) with some concrete types : int-Integer for example.
Behind the scenes, the Java compiler is rewriting the last statement ("I must unbox a and b to apply the sum operator with primitive datatypes, and box the result to assign it to object c") thus:
Number c = Integer.valueOf( a.intValue() + b.intValue() );
Java can't unbox a Number because it does not know at compile time the concrete type and hence it cannot guess its primitive counterpart.
You can do something like this
class Example <T extends Number> {
public Number add(T a, T b){
return new Double(a.doubleValue() + b.doubleValue());
}
}
Yes, Nathan is correct. If you want something like this, you have to write it yourself
public class Example <T extends Number> {
private final Calculator<T> calc;
public Example(Calculator<T> calc) {
this.calc = calc;
}
public T add(T a, T b){
return calc.add(a,b);
}
}
public interface Calculator<T extends Number> {
public T add(T a, T b);
}
public class IntCalc implements Calculator<Integer> {
public final static IntCalc INSTANCE = new IntCalc();
private IntCalc(){}
public Integer add(Integer a, Integer b) { return a + b; }
}
...
Example<Integer> ex = new Example<Integer>(IntCalc.INSTANCE);
System.out.println(ex.add(12,13));
Too bad Java has no type classes (Haskell) or implicit objects (Scala), this task would be a perfect use case...
There are similar questions to this one, and the answer is you can't do it like that.
You could check if a and b are an instance of Long/Double/Integer/etc. and delegate the add to methods like:
public Integer add(Integer a, Integer b) {
return a+b; // this actually uses auto boxing and unboxing to int
}
And you would need to create one for every type that extends Number, so that's not really feasible. In other words, don't use generics for numeric operations. Number as a superclass is pretty limited.
Consider Example<Number>, how would + work on that? There is no add or similar in Number or even the likes of Integer.
Worse consider final class FunkyNumber extends Number { ... weird stuff, no add op ... }.
Even the java runtime library has this problem, most of the methods dealing with primitives have to duplicate the same functionality.
The fastest option would be to write your code for one type and then copy it and replace the type to generate the methods for the other types. A short script should be enough to do this.

Generics in Java explanation for a vector method thats supposed to accept any type

I am following practices of coding to an interface in java as I learn it. I have a Function interface that has an executeFunction() method. But I would like to make this method generic. So the client can pass in a list of Strings, Boolean, Integers, Doubles etc. to run aggregate computation on them.
But I don't have a good grasp of generics so I would like some advice and an explanation of what the design approach I am in the process of coding is actually capable of doing. I'm thinking of having a StatsFunctions and ArithmeticFunctions concrete implementation classes that could be injected in other classes to use their fucntionalit. (Sorta trying the Strategy Pattern).
Here is my code:
import java.util.List;
public interface Function {
public <T> double executeFunction(List<T> vector);
}
The Question:
1). How can I use/alter this interface above to make it as generic and dynamic as possible?
If you could provide some examples of using this, it would be a huge help for my learning.
2). Why can't I do the below? I am getting an error saying: The operator "+" is undefined for the argument type T.
public class ArithmeticFunctions implements Function {
#Override
public <T> double executeFunction(List<T> vector) {
int retVal = 0;
for (int i = 0; i < vector.size(); i++) {
retVal = vector.get(i) + retVal;
}
return retVal;
}
}
Thank you in advance.
Better yet ::
public interface Function<F, T> {
T apply(F input);
}
Use it like this::
Function<Integer, Integer> doubleMyInput = new Function<Integer, Integer>() {
#Override
public Integer apply(Integer input) {
return input * 2;
}
};
The answer to the second question is not that simple. The error you see is a consequence of type erasure (this is how generics are implemented on the JVM).
Basically, your generic function declaration is equivalent to the following ::
public <T extends Object> double executeFunction(List<T> vector);
And the Java runtime does not see your type declarations, it only sees Objects.
To understand more clearly, let's assume that we are working in java 1.4, when generics didn't exist. Your interface would then look like this ::
public interface MyFunction {
public double executeFunction(List vector);
}
And the implementation ::
public class ArithmeticFunction implements MyFunction {
public double executeFunction(List vector) {
double retVal = 0;
for (int i = 0; i < vector.size(); i++) {
retVal += (((Double)vector.get(i))).doubleValue();
}
return retVal;
}
}
Note the cast, since there is really no other way to retrieve the value.
You can then do this ::
ArithmeticFunction af = new ArithmeticFunction();
// Good
af.executeFunction(new ArrayList(Arrays.asList(new Double[] {new Double(1), new Double(2)})));
However, this is also possible, and will get you a ClassCastException at runtime ::
// Bad !!
af.executeFunction(new ArrayList(Arrays.asList(new String[] {"A", "B", "C"})));
So to conclude, make a parallel between your implementation (and understand what happens at runtime)::
// does not compile
public class ArithmeticFunction implements MyFunction {
public double executeFunction(List<Integer> vector) {
int retVal = 0;
for (int i = 0; i < vector.size(); i++) {
retVal = vector.get(i) + retVal;
}
return retVal;
}
}
and the above-presented example.
Oh, and to fix your problem, you have to do::
public interface Function<T> {
public double executeFunction(List<T> vector);
}
I know that maybe some of the concepts presented here are unclear, so your best bet is to get up to speed using a tutorial on generics.
TL;DR: putting <T> on the method means that the actual type of the list will be known when the method is called. <T> on the interface means that the type of the list is known when the class is declared.
This declaration
public interface Function {
public <T> double executeFunction(List<T> vector);
}
means to something like:
The method executeFunction() can take in input a list of any type, and calculate a double from it.
Who calls this method can legally pass you List<Double>, List<Integer>, List<String> and so on. This is probably not what you want.
If you change the interface declaration like this:
public interface Function<T> {
public double executeFunction(List<T> vector);
}
you can declare your class in this way:
public class Summation implements Function<Double> {
public double executeFunction(List<Double> vector) {
// ...
}
}
Now you are sure that every element in vector is a Double, so you can safely sum them up.
public interface Function<T> {
public T executeFunction(List<T> vector);
}
Read as:
public interface Function with type T
That is why the function executeFunction returns that type T you declared above.
Note that T is always an Object, but Java can handle primitive types (int, double) through automatic boxing.

What does "Recursive type bound" in Generics mean?

I am reading the chapter on Generics from Effective Java[Item 27].
There is this paragraph in the book:
It is permissible, though relatively rare, for a type parameter to be bounded by some expression involving that type parameter itself. This is what’s known as a recursive type bound.
and this:
// Using a recursive type bound to express mutual comparability
public static <T extends Comparable<T>> T max(List<T> list) {...}
What is recursive type bound and how does the above piece of code help achieve mutual comparability?
What is recursive type bound
This: <T extends Comparable<T>>
Note that the type parameter T is also part of the signature of the super interface Comparable<T>.
and how does the above piece of code help achieve mutual comparability?
It ensures that you can only compare objects of type T. Without the type bound, Comparable compares any two Objects. With the type bound, the compiler can ensure that only two objects of type T are compared.
To understand the concept of recursive type bounds, let's solve a simple problem. This concept is easier to understand by solving a real problem. I'll provide the definition of the recursive type bound at the end, because it makes more sense after understanding the concept.
Problem
Assume that we have to sort the fruits by their sizes. And we are told that we can only compare fruits of the same types. For example, we can't compare apples with oranges (pun intended).
So, we create a simple type hierarchy like following,
Fruit.java
interface Fruit {
Integer getSize();
}
Apple.java
class Apple implements Fruit, Comparable<Apple> {
private final Integer size;
public Apple(Integer size) {
this.size = size;
}
#Override public Integer getSize() {
return size;
}
#Override public int compareTo(Apple other) {
return size.compareTo(other.size);
}
}
Orange.java
class Orange implements Fruit, Comparable<Orange> {
private final Integer size;
public Orange(Integer size) {
this.size = size;
}
#Override public Integer getSize() {
return size;
}
#Override public int compareTo(Orange other) {
return size.compareTo(other.size);
}
}
Main.java
class Main {
public static void main(String[] args) {
Apple apple1 = new Apple(3);
Apple apple2 = new Apple(4);
apple1.compareTo(apple2);
Orange orange1 = new Orange(3);
Orange orange2 = new Orange(4);
orange1.compareTo(orange2);
apple1.compareTo(orange1); // Error: different types
}
}
Solution
In this code, we are able to achieve our objective of being able to compare the same types, that is, apples with apples and oranges with oranges. When we compare an apple with an orange we get an error which is what we want.
Problem
The problem here is that the code for implementing the compareTo() method is duplicated for Apple and Orange class. And will be duplicated more in all the classes that we extend from the Fruit, for creating new fruits in the future. The amount of repeated code in our example is less but in real world the repeated code can be of hundreds of lines in each class.
Moving Repeated Code to Common Class
Fruit.java
class Fruit implements Comparable<Fruit> {
private final Integer size;
public Fruit(Integer size) {
this.size = size;
}
public Integer getSize() {
return size;
}
#Override public int compareTo(Fruit other) {
return size.compareTo(other.getSize());
}
}
Apple.java
class Apple extends Fruit {
public Apple(Integer size) {
super(size);
}
}
Orange.java
class Orange extends Fruit {
public Orange(Integer size) {
super(size);
}
}
Solution
In this step, we get rid of the repeated code of compareTo() method by moving it to a superclass. Our extended classes Apple and Orange are no longer polluted with common code.
Problem
Here the problem is that we are now able to compare different types, comparing apples to oranges no longer gives us an error:
apple1.compareTo(orange1); // No error
Introducing a Type Parameter
Fruit.java
class Fruit<T> implements Comparable<T> {
private final Integer size;
public Fruit(Integer size) {
this.size = size;
}
public Integer getSize() {
return size;
}
#Override public int compareTo(T other) {
return size.compareTo(other.getSize()); // Error: getSize() not available.
}
}
Apple.java
class Apple extends Fruit<Apple> {
public Apple(Integer size) {
super(size);
}
}
Orange.java
class Orange extends Fruit<Orange> {
public Orange(Integer size) {
super(size);
}
}
Solution
To restrict comparison of different types, we introduce a type parameter T. So that the comparable Fruit<Apple> cannot be compared to comparable Fruit<Orange>. Note our Apple and Orange classes; they now inherit from the types Fruit<Apple> and Fruit<Orange> respectively. Now if we try to compare different types, the IDE shows an error, our desired behaviour:
apple1.compareTo(orange1); // Error: different types
Problem
But in this step, our Fruit class doesn't compile. The getSize() method of T is unknown to the compiler. This is because the type parameter T of our
Fruit class doesn't have any bound. So, the T could be any class, it is not possible that every class would have a getSize() method. So the compiler is right in not recognizing the getSize() method of T.
Introducing a Recursive Type Bound
Fruit.java
class Fruit<T extends Fruit<T>> implements Comparable<T> {
private final Integer size;
public Fruit(Integer size) {
this.size = size;
}
public Integer getSize() {
return size;
}
#Override public int compareTo(T other) {
return size.compareTo(other.getSize()); // Now getSize() is available.
}
}
Apple.java
class Apple extends Fruit<Apple> {
public Apple(Integer size) {
super(size);
}
}
Orange.java
class Orange extends Fruit<Orange> {
public Orange(Integer size) {
super(size);
}
}
Final Solution
So, we tell the compiler that our T is a subtype of Fruit. In other words, we specify the upper bound T extends Fruit<T>. This makes sure that only subtypes of Fruit are allowed as type arguments. Now the compiler knows that the getSize() method can be found in the subtype of Fruit class (Apple, Orange etc.) because the Comparable<T> also receives our type(Fruit<T>) that contains the getSize() method.
This allows us to get rid of the repeated code of compareTo() method and also allows us to compare the fruits of the same types, apples with apples and oranges with oranges.
Now the compareTo() method can be used inside the max() function given in the question.
Definition of a Recursive Type Bound
In generics, when a reference type has a type parameter that is bounded by the reference type itself, then that type parameter is said to have a recursive type bound.
In our example, the generic type Fruit<T extends Fruit<T>>, Fruit is our reference type, its type parameter T is bounded by the Fruit itself, so, the type parameter T has a recursive type bound Fruit<T>.
A recursive type is one that includes a function that uses that type itself as a type for some argument or its return value. In our example, compareTo(T other) is the function of the recursive type that takes the same recursive type as an argument.
Caveat
There is a caveat in this pattern. The compiler doesn’t prevent us from creating a class with a type argument of another subtype:
class Orange extends Fruit<Orange> {...}
class Apple extends Fruit<Orange> {...} // No error
Note in the Apple class above, by mistake we passed Orange instead of the Apple itself as a type argument. This results in the compareTo(T other) method to take Orange instead of Apple. Now we no longer get error while comparing different types and suddenly not able to compare apples with apples:
apple1.compareTo(apple2); // Error
apple1.compareTo(orange1); // No error
So, the developer needs to be careful while extending the classes.
That's it! Hope that helps.
There is an entry in the Java Generics FAQ written by Angelika Langer which explains the details of such declaration: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106

Categories

Resources