Suppose I have the following class (for demonstration purposes)
package flourish.lang.data;
public class Toyset implements Comparable<Toyset> {
private Comparable<?>[] trains;
#Override
public int compareTo(Toyset o) {
for (int i =0; i<trains.length; i++) {
if (trains[i].compareTo(o.trains[i]) < 0)
return -1;
}
return 1;
}
}
The compiler tells me
"The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>)"
How can I deal with the fact that I want to put different Comparables into trains?
Sure I could remove the parameters and go with raw types, but that seems like a little bit of a cop-out.
EDIT:
Perhaps the example I've given is a little obtuse. What I'm trying to understand is whether generics should always be used with Comparables. e.g. If the class of the object I want compare is not known until runtime:
public class ComparisonTool {
public static int compareSomeObjects(final Class<? extends Comparable> clazz, final Object o1, final Object o2) {
return clazz.cast(o1).compareTo(clazz.cast(o2));
}
public static void main(String[] args) {
System.out.println(compareSomeObjects(Integer.class, new Integer(22), new Integer(33)));
}
}
If I replace Comparable with Comparable<?> then the compiler complains (as above) because the two cast operations are not guaranteed to be the same class (capture#1 of ? vs capture#2 of ?). On the other hand, I can't replace them with Comparable<Object> either, because then the call in main() doesn't match the method signature (i.e. Integer implements Comparable<Integer> and not Comparable<Object>. Using the raw type certainly 'works', but is this the right approach?
The problem is that one instance might have a Comparable<TrainA> and the other contain Comapable<TrainB> and the compare method of Comparable<TrainA> will not accept an instance of TrainB. This is what you have set up with the wildcard.
Your better bet is to put a common super type in the Comparable ie. Comparable<Toy> or Comparable<Object>.
By declaring your trains field to be of type Comparable<?>[], you're asserting that it's an array of some specific type—and that you don't happen to know which type it is. Two different instances of Toyset will each have trains fields that hold sequences of some specific type, but each has a different specific type in mind. The compiler is warning you that there's nothing in the code asserting that the specific types of the arrays pointed to be the various trains fields in Toyset instances will have any subtype or supertype relationship.
In this case, falling back to a raw type is honest; you don't have anything meaningful to say about the type of objects being compared. You could instead try using Comparable<Object>, which allows rather weak use of a type parameter.
The design strikes me as odd. I'm assuming it's elided from something much larger. Toy sets can be compared, which in turn depends on a lexicographic comparison of the trains contained in each toy set. That's fine, but why is there no upper bound type that all trains have in common?
Related
I have this:
class Male extends Person{..}
class Women extends Person{..}
// returns true if the return type of the given function is of type Women
boolean isReturnTypeWomen(Function<Integer, Person> function){
Class<?> type = function.getClass().getMethods()[0].getReturnType();
return type.isInstance(Women.class) ? true : false;
}
However, it always return true because type is always Object.
How can I check the instance type of the second parameter (the return type) of the given Function)?
Some Function subclasses will provide an apply method with covariant return type and a synthetic bridge to forward invocation across. However, Function instances will typically be lambdas or function references, so will not.
Consider, as a counterexample, the following method.
public static <T,R> Function<T,R> nothing(Function<T,R> fun) {
return t -> fun.apply(t);
}
The Function returned by this method will always be of the same class, but T may change. Therefore the class cannot reference the type.
A benefit of this is that the function objects do not need to carry around the overhead of extra data to represent type arguments, which are of no use in type-safe code anyway.
It can't not be - the parameter is a Function<Integer, String>.
getMethods[0] doesn't work. For example:
public class Example implements Function<Integer, String> {
public void completelyUnrelatedMethod() {}
public String apply(Integer i) { return null; }
}
This will return void here.
More generally there is no need for that runtime check - the generics take care of it:
Function<Integer, Integer> ohDearThisDoesNotReturnAString = a -> a;
isReturnTypeString(ohDearThisDoesNotReturnAString);
The above doesn't even compile.
To do a deep dive on your actual code, which utterly does not work:
Generics are erased, which mostly means that generics are usually a figment of the compiler's imagination. At runtime the information is simply gone. This isn't always true, but it usually is or can always be, so what you want (a runtime check) is impossible to guarantee.
In addition, you've messed up the check. isInstance does what instanceof does: It requires a type and some object. What you have is 2 instances of Class<?>; the right method for this is isAssignableFrom, not isInstance. As you have discovered, it doesn't work and cannot work - that's that erasure thing.
I'm a newbie in Generic and my question is: what difference between two functions:
function 1:
public static <E> void funct1 (List<E> list1) {
}
function 2:
public static void funct2(List<?> list) {
}
The first signature says: list1 is a List of Es.
The second signature says: list is a List of instances of some type, but we don't know the type.
The difference becomes obvious when we try to change the method so it takes a second argument, which should be added to the list inside the method:
import java.util.List;
public class Experiment {
public static <E> void funct1(final List<E> list1, final E something) {
list1.add(something);
}
public static void funct2(final List<?> list, final Object something) {
list.add(something); // does not compile
}
}
The first one works nicely. And you can't change the second argument into anything that will actually compile.
Actually I just found an even nicer demonstration of the difference:
public class Experiment {
public static <E> void funct1(final List<E> list) {
list.add(list.get(0));
}
public static void funct2(final List<?> list) {
list.add(list.get(0)); // !!!!!!!!!!!!!! won't compile !!!!!!!!!
}
}
One might as why do we need <?> when it only restricts what we can do with it (as #Babu_Reddy_H did in the comments). I see the following benefits of the wildcard version:
The caller has to know less about the object he passes in. For example if I have a Map of Lists: Map<String, List<?>> I can pass its values to your function without specifying the type of the list elements. So
If I hand out objects parameterized like this I actively limit what people know about these objects and what they can do with it (as long as they stay away from unsafe casting).
These two make sense when I combine them: List<? extends T>. For example consider a method List<T> merge(List<? extends T>, List<? extends T>), which merges the two input lists to a new result list. Sure you could introduce two more type parameters, but why would you want to? It would be over specifying things.
finally wildcards can have lower bounds, so with lists you can make the add method work, while get doesn't give you anything useful. Of course that triggers the next question: why don't generics have lower bounds?
For a more in depth answer see: When to use generic methods and when to use wild-card? and http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203
Generics makes the collection more type safe.
List<E> : E here is the Type Parameter, which can be used to determine the content type of the list, but there was No way to check what was the content during the runtime.
Generics are checked only during compilation time.
<? extends String> : This was specially build into java, to handle the problem which was with the Type Parameter. "? extends String" means this List can have
objects which IS-A String.
For eg:
Animal class
Dog class extends Animal
Tiger class extends Animal
So using "public void go(ArrayList<Animal> a)" will NOT accept Dog or Tiger as its content but Animal.
"public void go(ArrayList<? extends Animal> a)" is whats needed to make the ArrayList take in Dog and Tiger type.
Check for references in Head First Java.
List<E> as a parameter type says that the parameter must be a list of items with any object type. Moreover, you can bind the E parameter to declare references to list items inside the function body or as other parameter types.
The List<?> as a parameter type has the same semantics, except that there is no way to declare references to the items in the list other than to use Object. Other posts give additional subtle differences.
The first is a function that accepts a parameter that must be a list of items of E type.
the second example type is not defined
List<?> list
so you can pass list of any type of objects.
I usually explain the difference between <E> and <?> by a comparison with logical quantifications, that is, universal quantification and existential quantification.
corresponds to "forall E, ..."
corresponds to "there exists something(denoted by ) such that ...."
Therefore, the following generic method declaration means that, for all class type E, we define funct1
public static <E> void funct1 (List<E>; list1) {
}
The following generic method declaration means that, for some existing class denoted by <?>, we define funct2.
public static void funct2(List<?> list) {
}
(Since your edit) Those two function signatures have the same effect to outside code -- they both take any List as argument. A wildcard is equivalent to a type parameter that is used only once.
In addition to those differences mentioned before, there is also an additional difference: You can explicitly set the type arguments for the call of the generic method:
List<Apple> apples = ...
ClassName.<Banana>funct2(apples); // for some reason the compiler seems to be ok
// with type parameters, even though the method has none
ClassName.<Banana>funct1(apples); // compiler error: incompatible types: List<Apple>
// cannot be converted to List<Banana>
(ClassName is the name of the class containing the methods.)
In this context, both wild card (?) and type parameter (E) will do the same for you. There are certain edges based on the use cases.
Let's say if you want to have a method which may have more than one params like:
public void function1(ArrayList<?> a, ArrayList<?> b){
// some process
}
public <T> void function2(ArrayList<T> a, ArrayList<T> b){
// some process
}
in function1 a can be AL of String and b can be AL of the Integer so it is not possible to control the type of both the params but this is easy for the function2.
We should use the Type Params (function 2) if we want to use the type later in the method or class
There are some features in WildCard and Type param:
WildCard(?)
It support the upper and lower bound in the type while the Type param (E) supports only upper bound.
Type Param(E)
SomeTime we do not need to pass the actual type ex:
ArrayList<Integer> ai = new ArrayList<Integer>();
ArrayList<Double> ad = new ArrayList<Double>();
function2(ai, ad);
//It will compile and the T will be Number.
In this case, the compiler infers the type argument for us based on the type of actual arguments
Probably I am missing something and maybe my assumptions were wrong, but I thought that when I declare parametrized method with type T then no matter how much variables there are with that type it is still the same type. But I see that this compiles and it oposses my view.
static <T> void f(T a, T b) { }
public static void main(String[] args) {
f(Integer.MIN_VALUE, "...");
}
So if my method is parametrized with one type and I am using that one type in two paramteres why does it allow me to send two objects with two totally different types? I guess it comes down to treating T as Object?
Although Integer and String are two different types, they still share a common super-type. Serializable.
To verify this, lets return T,
static <T> T f(T a, T b) {
return null;
}
Serializable s = f(Integer.MIN_VALUE, "..."); // compiles
The compiler will resolve (or infer, not sure about the technical term) to the most specific type. For example,
Number number = f(Integer.MAX_VALUE, BigDecimal.ONE);
Now, the type resolved is Number because both types are subtypes of Number,as well as Serializable, as well as Object of course.
I'm a newbie in Generic and my question is: what difference between two functions:
function 1:
public static <E> void funct1 (List<E> list1) {
}
function 2:
public static void funct2(List<?> list) {
}
The first signature says: list1 is a List of Es.
The second signature says: list is a List of instances of some type, but we don't know the type.
The difference becomes obvious when we try to change the method so it takes a second argument, which should be added to the list inside the method:
import java.util.List;
public class Experiment {
public static <E> void funct1(final List<E> list1, final E something) {
list1.add(something);
}
public static void funct2(final List<?> list, final Object something) {
list.add(something); // does not compile
}
}
The first one works nicely. And you can't change the second argument into anything that will actually compile.
Actually I just found an even nicer demonstration of the difference:
public class Experiment {
public static <E> void funct1(final List<E> list) {
list.add(list.get(0));
}
public static void funct2(final List<?> list) {
list.add(list.get(0)); // !!!!!!!!!!!!!! won't compile !!!!!!!!!
}
}
One might as why do we need <?> when it only restricts what we can do with it (as #Babu_Reddy_H did in the comments). I see the following benefits of the wildcard version:
The caller has to know less about the object he passes in. For example if I have a Map of Lists: Map<String, List<?>> I can pass its values to your function without specifying the type of the list elements. So
If I hand out objects parameterized like this I actively limit what people know about these objects and what they can do with it (as long as they stay away from unsafe casting).
These two make sense when I combine them: List<? extends T>. For example consider a method List<T> merge(List<? extends T>, List<? extends T>), which merges the two input lists to a new result list. Sure you could introduce two more type parameters, but why would you want to? It would be over specifying things.
finally wildcards can have lower bounds, so with lists you can make the add method work, while get doesn't give you anything useful. Of course that triggers the next question: why don't generics have lower bounds?
For a more in depth answer see: When to use generic methods and when to use wild-card? and http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203
Generics makes the collection more type safe.
List<E> : E here is the Type Parameter, which can be used to determine the content type of the list, but there was No way to check what was the content during the runtime.
Generics are checked only during compilation time.
<? extends String> : This was specially build into java, to handle the problem which was with the Type Parameter. "? extends String" means this List can have
objects which IS-A String.
For eg:
Animal class
Dog class extends Animal
Tiger class extends Animal
So using "public void go(ArrayList<Animal> a)" will NOT accept Dog or Tiger as its content but Animal.
"public void go(ArrayList<? extends Animal> a)" is whats needed to make the ArrayList take in Dog and Tiger type.
Check for references in Head First Java.
List<E> as a parameter type says that the parameter must be a list of items with any object type. Moreover, you can bind the E parameter to declare references to list items inside the function body or as other parameter types.
The List<?> as a parameter type has the same semantics, except that there is no way to declare references to the items in the list other than to use Object. Other posts give additional subtle differences.
The first is a function that accepts a parameter that must be a list of items of E type.
the second example type is not defined
List<?> list
so you can pass list of any type of objects.
I usually explain the difference between <E> and <?> by a comparison with logical quantifications, that is, universal quantification and existential quantification.
corresponds to "forall E, ..."
corresponds to "there exists something(denoted by ) such that ...."
Therefore, the following generic method declaration means that, for all class type E, we define funct1
public static <E> void funct1 (List<E>; list1) {
}
The following generic method declaration means that, for some existing class denoted by <?>, we define funct2.
public static void funct2(List<?> list) {
}
(Since your edit) Those two function signatures have the same effect to outside code -- they both take any List as argument. A wildcard is equivalent to a type parameter that is used only once.
In addition to those differences mentioned before, there is also an additional difference: You can explicitly set the type arguments for the call of the generic method:
List<Apple> apples = ...
ClassName.<Banana>funct2(apples); // for some reason the compiler seems to be ok
// with type parameters, even though the method has none
ClassName.<Banana>funct1(apples); // compiler error: incompatible types: List<Apple>
// cannot be converted to List<Banana>
(ClassName is the name of the class containing the methods.)
In this context, both wild card (?) and type parameter (E) will do the same for you. There are certain edges based on the use cases.
Let's say if you want to have a method which may have more than one params like:
public void function1(ArrayList<?> a, ArrayList<?> b){
// some process
}
public <T> void function2(ArrayList<T> a, ArrayList<T> b){
// some process
}
in function1 a can be AL of String and b can be AL of the Integer so it is not possible to control the type of both the params but this is easy for the function2.
We should use the Type Params (function 2) if we want to use the type later in the method or class
There are some features in WildCard and Type param:
WildCard(?)
It support the upper and lower bound in the type while the Type param (E) supports only upper bound.
Type Param(E)
SomeTime we do not need to pass the actual type ex:
ArrayList<Integer> ai = new ArrayList<Integer>();
ArrayList<Double> ad = new ArrayList<Double>();
function2(ai, ad);
//It will compile and the T will be Number.
In this case, the compiler infers the type argument for us based on the type of actual arguments
I am trying to implement an algorithm that needs to compare some elements based on an ordering defined by an (any given) enum type, so I am trying to specialize it using enums in template definition. I tried with simple code to see if my idea would work, but I couldn't make it compile. Any ideas on how to approach the problem. Here is my code:
public class Algorithm <T extends Enum<T> >{
public TLCAlgorithm(){
T t1;
T t2;
if (t1<t2){
//do something
}
}
Essentially t1 and t2 will be different values of that enum type defined somewhere else. I am planning to have different enum types defining different kinds of orderings, so that by instantiating the class with a different enum type, the algorithm should behave differently. I would be instantiating as this: Algorithm<Ordering1> alg1=new Algorithm<Ordering1>().
Since you're calling this a "template", I'm guessing that you're coming from a C++ background. You should be aware that Java generics work very differently from C++ templates, despite the similar syntax: a generic method can't be specialized for different types like a function template can. The same compiled bytecode is used for all types of data.
The usual way to provide a customized ordering for a type in Java is by implementing the Comparator interface. To provide several orderings for a class Foo, for example, you'd write several classes that all implement Comparator<Foo> and define the compare(Foo, Foo) method differently in each one. Your algorithm can take an argument of type Comparator<Foo>, and the caller can pass an instance of one of those implementations.
You can also implement Comparator in an enum and implement compare separately for each enumeration value:
public enum Ordering implements Comparator<Person> {
BY_NAME {
#Override
public int compare(Person a, Person b) {
// Compare people's names...
}
},
BY_AGE {
#Override
public int compare(Person a, Person b) {
// Compare people's ages...
}
}
}
public class Example {
public void algorithm(Comparator<Person> comparator) {
Person a = // ...
Person b = // ...
if (comparator.compare(a, b) > 0) {
// ...
}
}
public void caller() {
algorithm(Ordering.BY_NAME); // Run algorithm using name ordering
algorithm(Ordering.BY_AGE); // Run algorithm using age ordering
}
}
Please change the proper Constructor name.
public Algorithm()
Use the ordinal method. It will give the order no of enum.
Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as java.util.EnumSet and java.util.EnumMap.
if (t1.ordinal()<t2.ordinal()){
Use Condition like that.