Consider the following constructor for the class Foo (which for the sake of clarity is not a generic class):
public <T> Foo(T obj) { }
This is valid syntax for constructors, just like with normal generic methods.
But what is the use of this syntax? Typically generic methods provide type safety for their return type, and can benefit from type inference by the compiler. For example:
Pair<String, Integer> stringInt = Pair.of("asfd", 1234);
But a call to a constructor always returns an instance of its declaring class, so its type parameters have no effect on the return type. The constructor above could just be replaced with its erasure:
public Foo(Object obj) { }
Of course generics aren't only about type safety for return types. The constructor might just want to constrain the type of argument(s) being passed in. However, the above reasoning still applies for a bounded type parameter:
public <N extends Number> Foo(N number) { }
public Foo(Number number) { } //same thing
Even nested type parameters with bounds are handled using wildcards:
public <N extends Number, L extends List<N>> Foo(L numList) { }
public Foo(List<? extends Number> numList) { } //same thing
So what is a legitimate use case for having a generic constructor?
Here's a possible one, adapted from functional programming. Suppose we have a Stream type that has some internal state, repeatedly yielding new elements until it returns null. The outside callers don't care what the internal state type of the stream type is, so you might get something like
class Stream<E> {
<S> Stream(S initialState, StepFunction<E, S> stepFun) {
...
}
}
without the recipient having to know what the internal state type is.
One thing I can think off of the top of my head is that you can ensure that bounds are fulfilled in the same way across multiple parameters.
Take an obviously stupid and contrived but valid constructor that copies a list from a source to a target:
public <T> Foo (List<T> listA, List<T> listB) {
listA.addAll(listB);
}
Using wildcards here would quickly become pretty nasty and probably not do what you want anyway. It would also be a totally arbitrary restriction to disallow it. So it makes sense to me that the language spec allows it.
One use case that I can think of is when you want to constrain a constructor argument to more than one type. Only the generic syntax allows you to declare a constructor taking a List of Numbers that also implements RandomAccess:
public <L extends List<? extends Number> & RandomAccess> Foo(L raNumList) { }
...
Foo f1 = new Foo(new ArrayList<Integer>());
Foo f2 = new Foo(new LinkedList<Integer>()); //compiler error
You can enforce certain constraints for the constructor parameters. E.g. the following code requires two parameters which implement the interfaces InterfaceA and InterfaceB.
<T extends InterfaceA & InterfaceB > Foo(T t1, T t2) {
}
The main use is to ensure that type constraints are met between multiple parameters. Here's an example that puts a bunch of components on an assembly line in the right order:
public <T> AssemblyLine(T[] starting, List<T> components) {
T[] a = components.toArray(starting);
Arrays.sort(a);
this.conveyorBelt.add(a);
}
Here the <T> ensures that T[] and List<T> hold the same type T, and not (say), Integer[] and List<string>.
Related
I had to write this function that takes the functional interface mapper and maps the elements of a stack to type <R>. My question is why the extra generic before the return type Stack<R> is necessary in the map function?
public <R> Stack<R> map(Function<E, R> mapper) {
}
A class can be generic or not, but whatever your class is public class MyClass or public class MyClass<E> it might happen that you would like to offer a method that uses a generic parameter for itself only, that no other methods in your class are using.
So the <R> here :
public <R> Stack<R> map(Function<E, R> mapper) {
}
means : know that there is a specific parameter I will use here, but for that method only.
it could be specified the same way you would do in a class declaration :
public <R extends Serializable> Stack<R> map(Function<E, R> mapper) {
}
for example.
In your case, this parameter is used to link the type you return to the type you give in input of this method : it ensures that if you give a mapper of type Function<E, R>, you will receive an R object in return.
Another convenient use of these "extra" generic parameters on methods is the dynamic checking of the type of an object returned. I use it often :
public <T> T myMethod(Class<T> expectedClass, int a, int b) {
...
// My result comes in an object o.
Object o;
if (expectedClass.isInstance(o) == false) {
// ClassCastException
}
return (T)o; // You are sure it has the expected type.
}
Every time you deal with generics in Java, you have to explicitly tell the method (and the compiler) that you are dealing with that.
How to tell them is this way, adding the <T> to the method signature.
Quoting from the link below:
The in the method signature implies that the method will be dealing with generic type T. This is needed even if the method is returning void
This is a very shallow explanation but you can read more about here and here.
The first <R> describes the type that you can use in the method signature, so it adds a placeholder you can use (its a list of usable types anyway). In the Stack<R> or Function<E,R> the type parameter indicates, that the given generic type must be used from the declared types.
Sometimes it seems unnecessary, but suppose you want to add some bounds to your type.
public <T extends SomeObject & Comparable> Stack<T> map(T x)
It will be ugly to write down the whole expression to every places where you want to use them.
Also if you use it for example as an array, you can't do it there:
public <T extends SomeObject & Comparable> Stack<T> map(T[] x)
So the first one is the declaration of a type as a placeholder. And the others is the use side of the variance. Then the compiler can check that everything is ok at call sites before type erasure happend.
It call the 'Generic Method'.The <R> means the type of the parameter of the method and it will be certain only when method invocation.
I am reading about generic methods from OracleDocGenericMethod. I am pretty confused about the comparison when it says when to use wild-card and when to use generic methods.
Quoting from the document.
interface Collection<E> {
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
We could have used generic methods here instead:
interface Collection<E> {
public <T> boolean containsAll(Collection<T> c);
public <T extends E> boolean addAll(Collection<T> c);
// Hey, type variables can have bounds too!
}
[…]
This tells us that the type argument is being used for polymorphism;
its only effect is to allow a variety of actual argument types to be
used at different invocation sites. If that is the case, one should
use wildcards. Wildcards are designed to support flexible subtyping,
which is what we're trying to express here.
Don't we think wild card like (Collection<? extends E> c); is also supporting kind of
polymorphism? Then why generic method usage is considered not good in this?
Continuing ahead, it states,
Generic methods allow type parameters to be used to express
dependencies among the types of one or more arguments to a method
and/or its return type. If there isn't such a dependency, a generic
method should not be used.
What does this mean?
They have presented the example
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src) {
...
}
[…]
We could have written the signature for this method another way,
without using wildcards at all:
class Collections {
public static <T, S extends T> void copy(List<T> dest, List<S> src) {
...
}
The document discourages the second declaration and promotes usage of first syntax? What's the difference between the first and second declaration? Both seems to be doing the same thing?
Can someone put light on this area.
There are certain places, where wildcards, and type parameters do the same thing. But there are also certain places, where you have to use type parameters.
If you want to enforce some relationship on the different types of method arguments, you can't do that with wildcards, you have to use type parameters.
Taking your method as example, suppose you want to ensure that the src and dest list passed to copy() method should be of same parameterized type, you can do it with type parameters like so:
public static <T extends Number> void copy(List<T> dest, List<T> src)
Here, you are ensured that both dest and src have same parameterized type for List. So, it's safe to copy elements from src to dest.
But, if you go on to change the method to use wildcard:
public static void copy(List<? extends Number> dest, List<? extends Number> src)
it won't work as expected. In 2nd case, you can pass List<Integer> and List<Float> as dest and src. So, moving elements from src to dest wouldn't be type safe anymore.
If you don't need such kind of relation, then you are free not to use type parameters at all.
Some other difference between using wildcards and type parameters are:
If you have only one parameterized type argument, then you can use wildcard, although type parameter will also work.
Type parameters support multiple bounds, wildcards don't.
Wildcards support both upper and lower bounds, type parameters just support upper bounds. So, if you want to define a method that takes a List of type Integer or it's super class, you can do:
public void print(List<? super Integer> list) // OK
but you can't use type parameter:
public <T super Integer> void print(List<T> list) // Won't compile
References:
Angelika Langer's Java Generics FAQs
Consider following example from The Java Programming by James Gosling 4th edition below where we want to merge 2 SinglyLinkQueue:
public static <T1, T2 extends T1> void merge(SinglyLinkQueue<T1> d, SinglyLinkQueue<T2> s){
// merge s element into d
}
public static <T> void merge(SinglyLinkQueue<T> d, SinglyLinkQueue<? extends T> s){
// merge s element into d
}
Both of the above methods have the same functionality. So which is preferable? Answer is 2nd one. In the author's own words :
"The general rule is to use wildcards when you can because code with wildcards
is generally more readable than code with multiple type parameters. When deciding if you need a type
variable, ask yourself if that type variable is used to relate two or more parameters, or to relate a parameter
type with the return type. If the answer is no, then a wildcard should suffice."
Note: In book only second method is given and type parameter name is S instead of 'T'. First method is not there in the book.
In your first question: It means that if there is a relation between the parameter's type and the method's return type then use a generic.
For example:
public <T> T giveMeMaximum(Collection<T> items);
public <T> Collection<T> applyFilter(Collection<T> items);
Here you are extracting some of the T following a certain criteria. If T is Long your methods will return Long and Collection<Long>; the actual return type is dependent on the parameter type, thus it is useful, and advised, to use generic types.
When this is not the case you can use wild card types:
public int count(Collection<?> items);
public boolean containsDuplicate(Collection<?> items);
In this two example whatever the type of the items in the collections the return types will be int and boolean.
In your examples:
interface Collection<E> {
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
those two functions will return a boolean whatever is the types of the items in the collections. In the second case it is limited to instances of a subclass of E.
Second question:
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src) {
...
}
This first code allow you to pass an heterogeneous List<? extends T> src as a parameter. This list can contain multiple elements of different classes as long as they all extends the base class T.
if you had:
interface Fruit{}
and
class Apple implements Fruit{}
class Pear implements Fruit{}
class Tomato implements Fruit{}
you could do
List<? extends Fruit> basket = new ArrayList<? extends Fruit>();
basket.add(new Apple());
basket.add(new Pear());
basket.add(new Tomato());
List<Fruit> fridge = new ArrayList<Fruit>();
Collections.copy(fridge, basket);// works
On the other hand
class Collections {
public static <T, S extends T> void copy(List<T> dest, List<S> src) {
...
}
constrain List<S> src to be of one particular class S that is a subclass of T. The list can only contain elements of one class (in this instance S) and no other class, even if they implement T too. You wouldn't be able to use my previous example but you could do:
List<Apple> basket = new ArrayList<Apple>();
basket.add(new Apple());
basket.add(new Apple());
basket.add(new Apple());
List<Fruit> fridge = new ArrayList<Fruit>();
Collections.copy(fridge, basket); /* works since the basket is defined as a List of apples and not a list of some fruits. */
Wildcard method is also generic - you could call it with some range of types.
The <T> syntax defines a type variable name. If a type variable has any use (e.g. in method implementation or as a constraint for other type), then it makes sense to name it, otherwise you could use ?, as anonymous variable. So, looks like just a short-cut.
Moreover, the ? syntax is not avoidable when you declare a field:
class NumberContainer
{
Set<? extends Number> numbers;
}
I will try and answer your question, one by one.
Don't we think wild card like (Collection<? extends E> c); is also
supporting kind of polymorphism?
No. The reason is that the bounded wildcard has no defined parameter type. It is an unknown. All it "knows" is that the "containment" is of a type E (whatever defined). So, it cannot verify and justify whether the value provided matches the bounded type.
So, it's no sensible to have polymorphic behaviours on wildcards.
The document discourages the second declaration and promotes usage of
first syntax? What's the difference between the first and second
declaration? Both seems to be doing the same thing?
The first option is better in this case as T is always bounded, and source will definitely have values (of unknowns) that subclasses T.
So, suppose that you want to copy all list of numbers, the first option will be
Collections.copy(List<Number> dest, List<? extends Number> src);
src, essentially, can accept List<Double>, List<Float>, etc. as there is an upper bound to the parameterized type found in dest.
The 2nd option will force you to bind S for every type you want to copy, like so
//For double
Collections.copy(List<Number> dest, List<Double> src); //Double extends Number.
//For int
Collections.copy(List<Number> dest, List<Integer> src); //Integer extends Number.
As S is a parameterized type that needs binding.
I hope this helps.
One other difference which is not listed here.
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o); // correct
}
}
But the following will result in compile time error.
static <T> void fromArrayToCollection(T[] a, Collection<?> c) {
for (T o : a) {
c.add(o); // compile time error
}
}
? means unknown
The general rule applies:
You can read from it, but not write
given simple pojo Car
class Car {
void display(){
}
}
This will compile
private static <T extends Car> void addExtractedAgain1(List<T> cars) {
T t = cars.get(1);
t.display();
cars.add(t);
}
This method won't compile
private static void addExtractedAgain2(List<? extends Car> cars) {
Car car = cars.get(1);
car.display();
cars.add(car); // will not compile
}
Another example
List<?> hi = Arrays.asList("Hi", new Exception(), 0);
hi.forEach(o -> {
o.toString() // it's ok to call Object methods and methods that don't need the contained type
});
hi.add(...) // nothing can be add here won't compile, we need to tell compiler what the data type is but we do not know
As far as I understand, there is only one use case when wildcard is strictly needed (i.e. can express something that you can not express using explicit type parameters). This is when you need to specify a lower bound.
Apart from that however wildcards serve to write more concise code, as described by the following statements in the document you mention:
Generic methods allow type parameters to be used to express
dependencies among the types of one or more arguments to a method
and/or its return type. If there isn't such a dependency, a generic
method should not be used.
[...]
Using wildcards is clearer and more concise than declaring explicit
type parameters, and should therefore be preferred whenever possible.
[...]
Wildcards also have the advantage that they can be used outside of
method signatures, as the types of fields, local variables and arrays.
Mainly -> Wildcards enforce generics at the parameter/argument level of a Non-Generic method.
Note. It can also be performed in genericMethod by default, but here instead of ? we can use T itself.
package generics;
public class DemoWildCard {
public static void main(String[] args) {
DemoWildCard obj = new DemoWildCard();
obj.display(new Person<Integer>());
obj.display(new Person<String>());
}
void display(Person<?> person) {
//allows person of Integer,String or anything
//This cannnot be done if we use T, because in that case we have to make this method itself generic
System.out.println(person);
}
}
class Person<T>{
}
SO wildcard has its specific usecases like this.
I am reading about generic methods from OracleDocGenericMethod. I am pretty confused about the comparison when it says when to use wild-card and when to use generic methods.
Quoting from the document.
interface Collection<E> {
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
We could have used generic methods here instead:
interface Collection<E> {
public <T> boolean containsAll(Collection<T> c);
public <T extends E> boolean addAll(Collection<T> c);
// Hey, type variables can have bounds too!
}
[…]
This tells us that the type argument is being used for polymorphism;
its only effect is to allow a variety of actual argument types to be
used at different invocation sites. If that is the case, one should
use wildcards. Wildcards are designed to support flexible subtyping,
which is what we're trying to express here.
Don't we think wild card like (Collection<? extends E> c); is also supporting kind of
polymorphism? Then why generic method usage is considered not good in this?
Continuing ahead, it states,
Generic methods allow type parameters to be used to express
dependencies among the types of one or more arguments to a method
and/or its return type. If there isn't such a dependency, a generic
method should not be used.
What does this mean?
They have presented the example
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src) {
...
}
[…]
We could have written the signature for this method another way,
without using wildcards at all:
class Collections {
public static <T, S extends T> void copy(List<T> dest, List<S> src) {
...
}
The document discourages the second declaration and promotes usage of first syntax? What's the difference between the first and second declaration? Both seems to be doing the same thing?
Can someone put light on this area.
There are certain places, where wildcards, and type parameters do the same thing. But there are also certain places, where you have to use type parameters.
If you want to enforce some relationship on the different types of method arguments, you can't do that with wildcards, you have to use type parameters.
Taking your method as example, suppose you want to ensure that the src and dest list passed to copy() method should be of same parameterized type, you can do it with type parameters like so:
public static <T extends Number> void copy(List<T> dest, List<T> src)
Here, you are ensured that both dest and src have same parameterized type for List. So, it's safe to copy elements from src to dest.
But, if you go on to change the method to use wildcard:
public static void copy(List<? extends Number> dest, List<? extends Number> src)
it won't work as expected. In 2nd case, you can pass List<Integer> and List<Float> as dest and src. So, moving elements from src to dest wouldn't be type safe anymore.
If you don't need such kind of relation, then you are free not to use type parameters at all.
Some other difference between using wildcards and type parameters are:
If you have only one parameterized type argument, then you can use wildcard, although type parameter will also work.
Type parameters support multiple bounds, wildcards don't.
Wildcards support both upper and lower bounds, type parameters just support upper bounds. So, if you want to define a method that takes a List of type Integer or it's super class, you can do:
public void print(List<? super Integer> list) // OK
but you can't use type parameter:
public <T super Integer> void print(List<T> list) // Won't compile
References:
Angelika Langer's Java Generics FAQs
Consider following example from The Java Programming by James Gosling 4th edition below where we want to merge 2 SinglyLinkQueue:
public static <T1, T2 extends T1> void merge(SinglyLinkQueue<T1> d, SinglyLinkQueue<T2> s){
// merge s element into d
}
public static <T> void merge(SinglyLinkQueue<T> d, SinglyLinkQueue<? extends T> s){
// merge s element into d
}
Both of the above methods have the same functionality. So which is preferable? Answer is 2nd one. In the author's own words :
"The general rule is to use wildcards when you can because code with wildcards
is generally more readable than code with multiple type parameters. When deciding if you need a type
variable, ask yourself if that type variable is used to relate two or more parameters, or to relate a parameter
type with the return type. If the answer is no, then a wildcard should suffice."
Note: In book only second method is given and type parameter name is S instead of 'T'. First method is not there in the book.
In your first question: It means that if there is a relation between the parameter's type and the method's return type then use a generic.
For example:
public <T> T giveMeMaximum(Collection<T> items);
public <T> Collection<T> applyFilter(Collection<T> items);
Here you are extracting some of the T following a certain criteria. If T is Long your methods will return Long and Collection<Long>; the actual return type is dependent on the parameter type, thus it is useful, and advised, to use generic types.
When this is not the case you can use wild card types:
public int count(Collection<?> items);
public boolean containsDuplicate(Collection<?> items);
In this two example whatever the type of the items in the collections the return types will be int and boolean.
In your examples:
interface Collection<E> {
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
those two functions will return a boolean whatever is the types of the items in the collections. In the second case it is limited to instances of a subclass of E.
Second question:
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src) {
...
}
This first code allow you to pass an heterogeneous List<? extends T> src as a parameter. This list can contain multiple elements of different classes as long as they all extends the base class T.
if you had:
interface Fruit{}
and
class Apple implements Fruit{}
class Pear implements Fruit{}
class Tomato implements Fruit{}
you could do
List<? extends Fruit> basket = new ArrayList<? extends Fruit>();
basket.add(new Apple());
basket.add(new Pear());
basket.add(new Tomato());
List<Fruit> fridge = new ArrayList<Fruit>();
Collections.copy(fridge, basket);// works
On the other hand
class Collections {
public static <T, S extends T> void copy(List<T> dest, List<S> src) {
...
}
constrain List<S> src to be of one particular class S that is a subclass of T. The list can only contain elements of one class (in this instance S) and no other class, even if they implement T too. You wouldn't be able to use my previous example but you could do:
List<Apple> basket = new ArrayList<Apple>();
basket.add(new Apple());
basket.add(new Apple());
basket.add(new Apple());
List<Fruit> fridge = new ArrayList<Fruit>();
Collections.copy(fridge, basket); /* works since the basket is defined as a List of apples and not a list of some fruits. */
Wildcard method is also generic - you could call it with some range of types.
The <T> syntax defines a type variable name. If a type variable has any use (e.g. in method implementation or as a constraint for other type), then it makes sense to name it, otherwise you could use ?, as anonymous variable. So, looks like just a short-cut.
Moreover, the ? syntax is not avoidable when you declare a field:
class NumberContainer
{
Set<? extends Number> numbers;
}
I will try and answer your question, one by one.
Don't we think wild card like (Collection<? extends E> c); is also
supporting kind of polymorphism?
No. The reason is that the bounded wildcard has no defined parameter type. It is an unknown. All it "knows" is that the "containment" is of a type E (whatever defined). So, it cannot verify and justify whether the value provided matches the bounded type.
So, it's no sensible to have polymorphic behaviours on wildcards.
The document discourages the second declaration and promotes usage of
first syntax? What's the difference between the first and second
declaration? Both seems to be doing the same thing?
The first option is better in this case as T is always bounded, and source will definitely have values (of unknowns) that subclasses T.
So, suppose that you want to copy all list of numbers, the first option will be
Collections.copy(List<Number> dest, List<? extends Number> src);
src, essentially, can accept List<Double>, List<Float>, etc. as there is an upper bound to the parameterized type found in dest.
The 2nd option will force you to bind S for every type you want to copy, like so
//For double
Collections.copy(List<Number> dest, List<Double> src); //Double extends Number.
//For int
Collections.copy(List<Number> dest, List<Integer> src); //Integer extends Number.
As S is a parameterized type that needs binding.
I hope this helps.
One other difference which is not listed here.
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o); // correct
}
}
But the following will result in compile time error.
static <T> void fromArrayToCollection(T[] a, Collection<?> c) {
for (T o : a) {
c.add(o); // compile time error
}
}
? means unknown
The general rule applies:
You can read from it, but not write
given simple pojo Car
class Car {
void display(){
}
}
This will compile
private static <T extends Car> void addExtractedAgain1(List<T> cars) {
T t = cars.get(1);
t.display();
cars.add(t);
}
This method won't compile
private static void addExtractedAgain2(List<? extends Car> cars) {
Car car = cars.get(1);
car.display();
cars.add(car); // will not compile
}
Another example
List<?> hi = Arrays.asList("Hi", new Exception(), 0);
hi.forEach(o -> {
o.toString() // it's ok to call Object methods and methods that don't need the contained type
});
hi.add(...) // nothing can be add here won't compile, we need to tell compiler what the data type is but we do not know
As far as I understand, there is only one use case when wildcard is strictly needed (i.e. can express something that you can not express using explicit type parameters). This is when you need to specify a lower bound.
Apart from that however wildcards serve to write more concise code, as described by the following statements in the document you mention:
Generic methods allow type parameters to be used to express
dependencies among the types of one or more arguments to a method
and/or its return type. If there isn't such a dependency, a generic
method should not be used.
[...]
Using wildcards is clearer and more concise than declaring explicit
type parameters, and should therefore be preferred whenever possible.
[...]
Wildcards also have the advantage that they can be used outside of
method signatures, as the types of fields, local variables and arrays.
Mainly -> Wildcards enforce generics at the parameter/argument level of a Non-Generic method.
Note. It can also be performed in genericMethod by default, but here instead of ? we can use T itself.
package generics;
public class DemoWildCard {
public static void main(String[] args) {
DemoWildCard obj = new DemoWildCard();
obj.display(new Person<Integer>());
obj.display(new Person<String>());
}
void display(Person<?> person) {
//allows person of Integer,String or anything
//This cannnot be done if we use T, because in that case we have to make this method itself generic
System.out.println(person);
}
}
class Person<T>{
}
SO wildcard has its specific usecases like this.
Trying to create a static field with a generic type doesn't compile:
class MyClass {
public static Function<Z, Z> blargh = new Function<Z, Z>() {
public Z apply(Z a) {
return a;
}
};
}
Eclipse says:
Multiple markers at this line
- Z cannot be resolved to a type
- Z cannot be resolved to a type
- Z cannot be resolved to a type
- Z cannot be resolved to a type
- The type new Function<Z,Z>(){} must implement the inherited
abstract method Function<Z,Z>.apply(Z)
but replacing all the Zs with a concrete type works just fine:
static Function<Integer, Integer> blargh = new Function<Integer, Integer>() {
public Integer apply(Integer a) {
return a;
}
};
What's going on here?
Context:
I was originally trying to figure out why this code uses a method instead of a field:
public static <T extends Throwable> F<T, String> eMessage() {
return new F<T, String>() {
public String f(final Throwable t) {
return t.getMessage();
}
};
}
Maybe it's to overcome this restriction?
the Function type is from Google's guava library.
Edit: Now I see the problem better.
I think that firstly you would have to declare the type as a class parameter:
class MyClass<Z> {
to get visibility, but now the reason you can't use it like that is because the static member should be shared among all the instances of the class. But since you could create instances with different type parameters, the static member depending on a particular type would not make sense.
You can only use class-level generics on member fields. For example:
public class MyClass<Z> {
private Function<Z, Z> function;
// ...
}
is correct. Declaring this static instead will break. Why?
Think about ArrayList. Its class declaration is something like:
public class ArrayList<E> extends AbstractList<E> implements List<E>, ... {
// ...
}
E has no context in a static sense, because static variables belong to all instances of ArrayList, but E can be different for each ArrayList instance:
// Here's one ArrayList with E as String
List<String> strs = new ArrayList<String>();
// And another with E as Boolean
List<Boolean> bools = new ArrayList<Boolean>();
So because E can change from instance to instance, it doesn't make sense to have an E variable at the static level.
Now you can declare static methods with generics, but in a totally different way. For example, Collections.sort could have a declaration like this:
public static <T> void sort(List<? extends T> list, Comparator<T> comparator)
Notice that T is declared as part of the method before the return type. This is defining the context of T within the method, and T can differ from call to call.
Post-edit remark: in your case, you don't have Z declared anywhere, so you won't be able to use it anyway. See my declaration above for MyClass. Notice how I used <Z> directly on the class? That means that Z will be some arbitrary type.
In the case of what you were trying to figure out, you should look at Function as a generic way of representing a transformation. Let's dissect your posted method:
public static <T extends Throwable> F<T, String> eMessage() {
return new F<T, String>() {
public String f(final Throwable t) {
return t.getMessage();
}
};
}
First, note that this is a method, not a static field like your OP, so it's legal to have generics here. Also, it's static, so any generics need to be declared before the return type. Here, they declare <T extends Throwable>, so T must be some kind of error or exception that extends Throwable. The return type is F<T, String>, which is a function that takes a T (a Throwable) and returns a String. The actual object declares an f method which does just that by calling Throwable.getMessage. Since the project is functionaljava, everything is based on the F class, so generics are everywhere.
Just remember:
Generics declared at the class level can only be used by non-static members and methods.
Generics declared at the method level are allowable, but don't refer to the class-level types, referring instead to types declared before the return type.
Generics declared at the static field level simply aren't allowed because they'll never have context for their concrete type.
I think the simplest answer might be that: although the JDK compiler is flexible in how it interprets generics, it is impossible to modify or specify the "Z" class given the semantics of your code.
In all use of generics, you must define a syntax which specifies the identity of the generic class that is being operated upon. For example (As in the examples above).
1) Use a generic, parameterized utility function. In this case, its obvious to the compiler because the specified class is sent as input the function.
2) Define the class itself as being generic, and non static. This would then require that the user of the class declare it with the proper specified class parameter.
Specifically, for Function classes, you are clearly defining a constrained class : one which takes "Z" as input, and returns "Z" as output. If you want to generify this, you might create a FunctionFactory class, which takes in, for example, a single instance of Z, and returns a type-specified function of type :
public static <Z> Function<Z,Z> functionFactory(final Z default){
return new Function<Z,Z>(){
#Override
public Z apply(Z input) {
// TODO Auto-generated method stub
if(input==null)
return default;
else
return input;
}
};
}
I'm trying to implement a sorted list as a simple exercise in Java. To make it generic I have an add(Comparable obj) so I can use it with any class that implements the Comparable interface.
But, when I use obj.compareTo(...) anywhere in the code I get "unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable" from the compiler (with -Xlint:unchecked option). The code works just fine but I can't figure out how to get rid of that annoying message.
Any hints?
In essence, this warning says that Comparable object can't be compared to arbitrary objects. Comparable<T> is a generic interface, where type parameter T specifies the type of the object this object can be compared to.
So, in order to use Comparable<T> correctly, you need to make your sorted list generic, to express a constraint that your list stores objects that can be compared to each other, something like this:
public class SortedList<T extends Comparable<? super T>> {
public void add(T obj) { ... }
...
}
Using an interface like Comparable as a method parameter doesn't make your class generic, declaring and using generic type parameters is how you make it generic.
Quick-n-dirty answer: You are receiving the warning because you are using Comparable, which is a generic interface, as a raw type, rather than giving it a specific type arguments, like Comparable<String>.
To fix this, make add() generic by specifying type parameters:
<T extends Comparable<? super T>> add(T obj) { ... }
But this quick fix won't fix the general problem that your class is unsafe. After all, shouldn't all the objects in your list be of the same type? This add method lets you still different types into the same list. What happens when you try to compare heterogeneous types (how do you compareTo an Object instance to an Number instance, or to a String instance)? You can depend on the user of the class to do the right thing and ensure they only stick 1 kind of thing in your list, but a generic class will let the compiler enforce this rule.
The better approach: The proper fix is that your sorted list class should be probably be generic overall, just like the other collection classes in java.util.
You would probably like something like:
public class SortedList<T extends Comparable<? super T>>
implements Iterable<T> {
...
public void add(T item) { ... }
public Iterator<T> iterator() { ... }
...
}
Note that when the class is generic, the add method uses the classes formal type parameter rather than declaring its own formal type parameter.
There should be plenty of tutorials on the web on how to create a generic class, but here's a quick example:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ002
class Pair<X,Y> {
private X first;
private Y second;
public Pair(X a1, Y a2) {
first = a1;
second = a2;
}
public X getFirst() { return first; }
public Y getSecond() { return second; }
public void setFirst(X arg) { first = arg; }
public void setSecond(Y arg) { second = arg; }
}
You need to "check" or define the Comparable object like so:
add(Comparable<Object> obj)