generic maximum function in Java [duplicate] - java

I've read awesome "Effective Java" by Joshua Bloch. But one example in the books is left unclear to me. It's taken from chapter about generics, exact item is "Item 28: Use bounded wildcards to increase API flexibility".
In this item it's shown how to write the most universal and bulletproof (at the type system point of view) version of the algorithm of selection maximum element from collection using bounded type parameters and bounded wildcard types.
The final signature of the static method written looks like this:
public static <T extends Comparable<? super T>> T max(List<? extends T> list)
And it's mostly the same as the one of Collections#max function from standard library.
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
I understand why we need bounded wildcard in T extends Comparable<? super T> type constraint, but is it really necessary in type of the argument? It seems to me that it will be the same if we leave just List<T> or Collection<T>, isn't it? I mean something like this:
public static <T extends Comparable<? super T>> T wrongMin(Collection<T> xs)
I've written the following silly example of using both signatures and don't see any diferrence:
public class Algorithms {
public static class ColoredPoint extends Point {
public final Color color;
public ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color;
}
#Override
public String toString() {
return String.format("ColoredPoint(x=%d, y=%d, color=%s)", x, y, color);
}
}
public static class Point implements Comparable<Point> {
public final int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public String toString() {
return String.format("Point(x=%d, y=%d)", x, y);
}
#Override
public int compareTo(Point p) {
return x != p.x ? x - p.x : y - p.y;
}
}
public static <T extends Comparable<? super T>> T min(Collection<? extends T> xs) {
Iterator<? extends T> iter = xs.iterator();
if (!iter.hasNext()) {
throw new IllegalArgumentException("Collection is empty");
}
T minElem = iter.next();
while (iter.hasNext()) {
T elem = iter.next();
if (elem.compareTo(minElem) < 0) {
minElem = elem;
}
}
return minElem;
}
public static <T extends Comparable<? super T>> T wrongMin(Collection<T> xs) {
return min(xs);
}
public static void main(String[] args) {
List<ColoredPoint> points = Arrays.asList(
new ColoredPoint(1, 2, Color.BLACK),
new ColoredPoint(0, 2, Color.BLUE),
new ColoredPoint(0, -1, Color.RED)
);
Point p1 = wrongMin(points);
Point p2 = min(points);
System.out.println("Minimum element is " + p1);
}
So can you suggest an example where such simplified signature will be inacceptable?
P.S. And why the heck there is T extends Object in official implementation?
Answer
Well, thanks to #Bohemian I've managed to figure out what's the difference between them.
Consider the following two auxiliary methods
private static void expectsPointOrColoredPoint(Point p) {
System.out.println("Overloaded for Point");
}
private static void expectsPointOrColoredPoint(ColoredPoint p) {
System.out.println("Overloaded for ColoredPoint");
}
Sure, it's not very smart to overload method both for superclass and its subclass, but it let us see what type of return value was actually inferred (points is List<ColoredPoint> as before).
expectsPointOrColoredPoint(min(points)); // print "Overloaded for ColoredPoint"
expectsPointOrColoredPoint(wrongMin(points)); // print "Overloaded for ColoredPoint"
For both methods inferred type was ColoredPoint.
Sometimes you want be explicit about type passed to overloaded function. You may do it a couple of ways:
You can cast:
expectsPointOrColoredPoint((Point) min(points)); // print "Overloaded for Point"
expectsPointOrColoredPoint((Point) wrongMin(points)); // print "Overloaded for Point"
Still no difference...
Or you can tell compiler what type should be inferred using syntax class.<type>method:
expectsPointOrColoredPoint(Algorithms.<Point>min(points)); // print "Overloaded for Point"
expectsPointOrColoredPoint(Algorithms.<Point>wrongMin(points)); // will not compile
Aha! Here is the answer. List<ColoredPoint> can't be passed to function expecting Collection<Point> because generics are not covariant (unlike arrays), but can be passed to function expecting Collection<? extends Point>.
I'm not sure where or who may prefer to use explicit type parameter in such case, but at least it shows where the wrongMin may be inappropriate.
And thanks to #erickson and #tom-hawtin-tackline for answers about purpose of T extends Object constraint.

The difference is in the type returned, especially influenced by inference, whereby the type may be a type hierarchically between the Comparable type and the List type. Let me give an example:
class Top {
}
class Middle extends Top implements Comparable<Top> {
#Override
public int compareTo(Top o) {
//
}
}
class Bottom extends Middle {
}
Using the signature you've provided:
public static <T extends Comparable<? super T>> T max(List<? extends T> list)
we can code this without errors, warnings or (importantly) casts:
List<Bottom> list;
Middle max = max(list); // T inferred to be Middle
And if you need a Middle result, without inference, you can explicitly type the call to Middle:
Comparable<Top> max = MyClass.<Middle>max(list); // No cast
or to pass to a method that accepts Middle (where inference won't work)
someGenericMethodThatExpectsGenericBoundedToMiddle(MyClass.<Middle>max(list));
I don't know if this helps, but to illustrate the types the compiler as allowed/inferred, the signature would look like this (not that this compiles, of course):
public static <Middle extends Comparable<Top>> Middle max(List<Bottom> list)

The difference between
T max(Collection<? extends T> coll)
and
T wrongMax(Collection<T> xs)
is that the return type of the second version is exactly the same as the collection's element type T, while in the first version T can be a super type of the element type.
The second question: the reason for T extends Object makes sure that T is a class and not an interface.
Update: A slightly more "natural" demonstration of the difference: Suppose you define these two methods:
static void happy(ColoredPoint p, Point q) {}
static void happy(Point p, ColoredPoint q) {}
And call the first one them like this:
happy(coloredPoint, min(points));
happy(coloredPoint, wrongMin(points));
The type inference engine could be able to deduce that in the first call the return type of min should be Point and the code would compile. The second call would fail to compile since the call to happy is ambiguous.
Unfortunately the type inference engine isn't powerful enough at least in Java 7, so in reality both calls fail to compile. The difference is that the first call can be fixed by specifying the type parameter as in Algorithms.<Point>min, while fixing the second call would require an explicit cast.

Not an easy one, but i'll try to be as specific as possible:
in T max(Collection<? extends T> coll)
you could pass an argument like this List<Animal> or List<Cat> or List<Dog>,
and in T wrongMax(Collection<T> xs)
where T is Animal you can't pass as an Argument this
List<Dog>, List<Cat> of course in Runtime you could add Cat or Dog objects in List<Animal> but in compilation time you wouldn't be able to pass a subclass of Animal in the Type of the List being passed as an argument in the wrongMax method, in the other hand, in the max method you could. Sorry for my english, i still learning it :), Regards.

Related

Overriding necessary to avoid runtime type check for Java generic method?

The following snippet of generic magic has saved me some grief by caching very expensive functions on Strings (which Phrase simply wraps).
public class Phrase {
private final ConcurrentHashMap<Function<? extends Phrase, ?>, Object> memos;
public final String text;
public <X, T extends Phrase> X memo(Function<T, X> app) {
return (X) memos.computeIfAbsent(app, unused -> app.apply((T) this));
}
}
// Example follows
public class Joke extends Phrase {
boolean isoffcolor;
}
public class BigramJokeEvaluator {
public Boolean static isFunny(Joke joke) {
return !joke.isoffcolor;
}
}
public class MilesAway {
public static void main(String[] args) {
// Boom
new Phrase("Moo goes the cow!").memo(BigramJokeEvaluator::isFunny);
}
}
I have several subclasses of Phrase, with their own respective functions, and when other modules use subclasses of Phrase along with those functions, it's up to the programmer to make sure type T of T extends Phrase lines up correctly.
Function<>'s are immutable so the runtime coercion of (X) is guaranteed. But if I want to make the coercion of T into a compile-time type check:
Is there some way I can forward the lower function's type constraint to the higher-level function's type constraint? (Effectively making memo in the case of Joke as if it was <X> X memo(Function<Joke, X>);) [Does Type Erasure prevent this?]
Do I have to make delegate functions in all the subclasses of Phrase?
Is there some trick other than 'just not making any mistakes'?
The best you can do is this:
public class Phrase<P extends Phrase<P>> {
private final ConcurrentHashMap<Function<P, ?>, Object> memos;
public final String text;
public <X> X memo(Function<P, X> app) {
return (X) memos.computeIfAbsent(app, unused -> app.apply((P) this));
}
}
class Joke extends Phrase<Joke> {...}
This is called F-bounded quantification and it's used by e.g. Enum<E extends Enum<E>>.
It's a bit of a pain in the neck but it generally works.
Note that it does not guarantee that P is the type of this:
class Joke extends Phrase<Joke> {}
// oops
class Troll extends Phrase<Joke> {}
It's also impossible to capture a Class<? extends Phrase<?>>:
{
Class<? extends Phrase<?>> j = Joke.class;
m( j ); // fails, but would pass if P was not F-bounded
}
static <P extends Phrase<P>> void m(Class<P> c) {}
But overall, it makes it harder to make the more likely types of mistakes.
Do I have to make delegate functions in all the subclasses of Phrase?
Delegating to subclasses is difficult because of 1. no covariant parameters and 2. erasure.
class Phrase {
...
<X> X memo(Function<Phrase, X> f) {...}
}
class Joke extends Phrase {
...
// this is a compiler error
// (technically, I think it's classified as
// "override-equivalent", but specified to fail)
<X> X memo(Function<Joke, X> f) {...}
}
(If that's the type of thing you're referring to by 'delegate'. Otherwise, feel free to clarify.)
You could delegate with a type parameter e.g.:
class Phrase<P> {
abstract <X> X memo(Function<P, X> f);
}
class Joke extends Phrase<Joke> {
#Override
<X> X memo(Function<Joke, X> f) {...}
}
This avoids the unchecked casting.
You should make a type parameter (here we call P) to represent the type of the subclass, and then for the method that cares about the relationship of P to its type parameter, we use a generic method to do it (it's static so it's "outside" the class):
class Phrase<P> {
final HashMap<Function<P, ?>, Object> memos = new HashMap<>();
public static <X, T extends Phrase<T>> X memo(T phrase, Function<T, X> app) {
return (X) phrase.memos.computeIfAbsent(app, unused -> app.apply(phrase));
}
}
Phrase.memo(new Phrase(), BigramJokeEvaluator::isFunny);

Use of type-parameters before a method/constructor in Java Generics

I'm studying generics in Java, and was getting along comfortably until I reached the topic- Creating a generic method.
I know that in Java, generics are used when you want to implement something irrespective of the data type that the program(or method) operates upon. So, you could have a generic class as Class Gen<T> and then in a non-generic class class GenDemo (which includes the main()). Then, you can create Gen references for different data types, such as Gen<Integer> iOB and Gen <String> strOB.
However, in the example given on creating a generic method, the book gives the following code:
//This is a simple generic method
class GenMethDemo
{
//determine if an object is in an array
static<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;
else
return false;
}
public static void main(String[] args)
{
//use isIn() on Integers
Integer nums[]={1,2,3,4,5};
if(isIn(2,nums))
System.out.println("2 is in nums");
if(!isIn(7,nums))
System.out.println("2 is in nums");
//use isIn() on Strings
String strs[]={"one", "two", "three", "four", "five"};
if(!(isIn("two", strs))
System.out.println("two is in strs");
}
}
I understand that this program is trying to determine if a given array consists of a specified object. But I can't wrap my head around this line:
static <T,V extends T> boolean isIn(T x, V[] y)
Thinking on the lines of what I've studied so far in generics, I know that there are two arguments of the Boolean function isIn(). But what are the type-paramaters <T, V extends T> doing before the return type of the function isIn()?
I understand the use of the keyword extends here; it acts as a bound for the type-parameter V, ie: V must be of the same type as T or a subclass of T, but I can't get further.
There is a similar use of type-parameters under the topic: Creating Generic Constructors, as:
class GenCons
{
private double val;
<T extends Number> GenCons(T arg)
{
val=arg.doubleValue();
}
void showVal()
{
System.out.println("Val: "+ val);
}
}
As before, I'm stumped by the line: <T extends Number> GenCons(T arg). Why is <T extends Number> used before the constructor is declared? It could also have been written like: GenCons(<T extends Number> arg)?
Any help would be highly appreciated.
Notice how in your GenMethDemo and GenCons classes, the class itself doesn't have a generic type. It's not class GenMethDemo<T, V extends T> -- instead, it's just class GenMethDemo.
So if GenMethDemo and GenCons aren't generic classes, how are you able to use generics? It seems to be a contradiction.
Well, Java also lets you define generic methods. If I do static<T,V extends T> boolean isIn(T x, V[] y), it's as if I had actually done class GenMethDemo<T, V extends T> except that the type variables T and V are scoped only to that particular method. This can be useful when you don't necessarily want the entire class to use generics; only a method or two where they're really needed.

Why producer in Collections.max() is a bounded wildcard? [duplicate]

In Java, the Collections class contains the following method:
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c)
Its signature is well-known for its advanced use of generics,
so much that it is mentioned in the Java in a Nutshell book
and in the official Sun Generics Tutorial.
However, I could not find a convincing answer to the following question:
Why is the formal parameter of type Collection<? extends T>, rather
than Collection<T>? What's the added benefit?
Type inference is a tricky topic that I'll admit that I don't know that much about. However, examine this example:
public class ScratchPad {
private static class A implements Comparable<A> {
public int compareTo(A o) { return 0; }
}
private static class B extends A {}
private static class C extends B {}
public static void main(String[] args)
{
Collection<C> coll = null;
B b = Scratchpad.<B>min(coll);
}
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c) {
return null;
}
//public static <T extends Object & Comparable<? super T>> T min(Collection<T> c) {
// return null;
//}
}
Consider that the first signature of min() allows the call to compile whereas the second does not. This isn't a very practical example, since one must ask why I would be explicitly typing the method to <B>, but perhaps there is an implicit inference where B would be the inferred type.
One benefit of the ? is that it prohibits additions of items to the Collection
I think it actually doesn't give you anything more for this method, however its a good habit to get into when T is part of the class and not just a static method.
They are including it here so it can become the new convention where every generic should be extended by ?
A class of T should follow PECS: What is PECS (Producer Extends Consumer Super)?
But a static method doesn't need to (at least the parameters, the return value should always)
This is to support a legacy signature of the method in Java 1.4 ( and before ).
Prior to Java 5 the signature for these methods was
public static Object min ( Collection c );
With multiple bounds the erasure rules make the first bound the raw type of the method, so without Object & the signature would be
public static Comparable min ( Collection c );
and legacy code would break.
This is taken from O'Reilly's Java Generics and Collections book, chapter 3.6
Building on the comments I put on Mark's answer, if you have something like
class Play {
class A implements Comparable<A> {
#Override
public int compareTo(A o) {
return 0;
}
}
class B extends A {
}
class C extends A {
}
public static <T extends Object & Comparable<? super T>> T min(
Collection<? extends T> c) {
Iterator<? extends T> i = c.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) < 0)
candidate = next;
}
return candidate;
}
public static List<? extends A> getMixedList() {
Play p = new Play();
ArrayList<A> c = new ArrayList<A>();
c.add(p.new C());
c.add(p.new B());
return c;
}
public static void main(String[] args) {
ArrayList<A> c = new ArrayList<A>();
Collection<? extends A> coll = getMixedList();
A a = Play.min(coll);
}
}
It's clearer that min returns an object of type A (the actual signature is <A> A Play.min(Collection<? extends A> c) ). If you leave min(Collection<T>) without the extends part then Play.min(coll) will have the following signature <? extends A> ? extends A Play.min(Collection<? extends A> c) which isn't as clear.

Generics methods - passing objects and invoking its method

I'm trying to understand how Generics works and wrote a method to test it.
I have created Object - Drink and its child object Coffee... and defined a generic method go1() to invoke the sip() method of both these objects...
I'm running in Eclipse and get an error - stating the method sip() is undefined for type V.
Can someone explain how this is handled?
class Drink{
public void sip(){
System.out.println("Im Drink method");
}
}
class Coffee extends Drink{
public void sip(){
System.out.println("Im Coffee method");
}
}
public class test{
public static <V> V go1(V o){
o.sip();
}
public static <V> void go(V v){
System.out.println(v.hashCode());
}
public static void main(String[] args) {
Drink s1 = new Drink();
go1(s1);
int i = 10;
String j ="test";
go(i);
go(j);
}
}
Just add bounds to the type parameter:
public static <V extends Drink> void go1(V o){
o.sip();
}
With type parameter bound, you get access to the non-static methods of the bound - Drink in this case, using the reference of that type parameter.
After edit:
For passing String and Integer to your method, you can think of which common upper bound would fit for both. The common supertype for String and Integer are:
Object
Serializable
Comparable<T>
So, you can have three kinds of bounds:
<V extends Object>
<V extends Serializable>
<V extends Comparable<V>>
So you just modify your go() method like:
public static <V extends Object> void go(V v){
System.out.println(v.hashCode());
}
References:
Java Generics FAQs
What is type parameter bounds?
What is difference between <? extends Object> and <E extends Object>?
The compiler decides if method calls are valid based on the type they are called on. You have
public static <V> V go1(V o){
o.sip();
}
but V is not a bounded type so the compiler can only be sure that it is at least of type Object. Object doesn't have a sip() method. You need to bound your type
public static <V extends Drink> V go1(V o){
o.sip();
}
This way the compiler knows that V is at least of type Drink. Drink has a sip() method.
The problem is that plain <V> can't be understood as a Drink but as a generic Object. You need to bind the generic to your Drink class, so declare the generic as <V extends Drink>.
More info: Generic Methods and Bounded Type Parameters
Just to aid your understanding..
Given that your overall objective is to further your understanding of Generics, I'd just like to point out that a simple interface or superclass object reference would be a simpler solution to your issue. i.e:
public void go1(Drink d)
{
d.sip();
}
A more classic example of Generics
Let's say you've got an object, Pair. Pair needs to be able to hold two of anything in Java, so you make those two things of type Object. What does that mean? It means you're always casting between Object and the desired type. So what do you do? You use generics.
public class Pair<F,S>
{
F first;
S second;
public Pair(F first, S second)
{
this.first = first;
this.second = second;
}
}
Now instead of having to cast, you simply state:
Pair<Integer, String> pair = new Pair<Integer, String>(10, "Ten");

Generic instance variable in non-generic class

I'm trying to write a class that has a generic member variable but is not, itself, generic. Specifically, I want to say that I have an List of values of "some type that implements comparable to itself", so that I can call sort on that list... I hope that makes sense.
The end result of what I'm trying to do is to create a class such that I can create an instance of said class with an array of (any given type) and have it generate a string representation for that list. In the real code, I also pass in the class of the types I'm passing in:
String s = new MyClass(Integer.class, 1,2,3).asString();
assertEquals("1 or 2 or 3", s);
String s = new MyClass(String.class, "c", "b", "a").asString();
assertEquals("\"a\" or \"b\" or \"c\"", s);
Originally I didn't even want to pass in the class, I just wanted to pass in the values and have the code examine the resulting array to pick out the class of the values... but that was giving me troubles too.
The following is the code I have, but I can't come up with the right mojo to put for the variable type.
public class MyClass {
// This doesn't work as T isn't defined
final List<T extends Comparable<? super T>> values;
public <T extends Comparable<? super T>> MyClass (T... values) {
this.values = new ArrayList<T>();
for(T item : values) {
this.values.add(item);
}
}
public <T extends Comparable<? super T>> List<T> getSortedLst() {
Collections.sort(this.values);
return this.values;
}
}
error on variable declaration line:
Syntax error on token "extends", , expected
Any help would be very much appreciated.
Edit: updated code to use List instead of array, because I'm not sure it can be done with arrays.
#Mark: From everything I've read, I really want to say "T is a type that is comparable to itself", not just "T is a type that is comparable". That being said, the following code doesn't work either:
public class MyClass {
// This doesn't work
final List<? extends Comparable> values;
public <T extends Comparable> MyClass (T... values) {
this.values = new ArrayList<T>();
for(T item : values) {
this.values.add(item);
}
}
public <T extends Comparable> List<T> getSortedLst() {
Collections.sort(this.values);
return this.values;
}
}
error on add line:
The method add(capture#2-of ? extends Comparable) in the type List<capture#2-of ? extends Comparable> is not applicable for the arguments (T)
error on sort line:
Type mismatch: cannot convert from List<capture#4-of ? extends Comparable> to List<T>
Conclusion:
What it comes down to, it appears, is that Java can't quite handle what I want to do. The problem is because what I'm trying to say is:
I want a list of items that are
comparable against themselves, and I
create the whole list at once from the
data passed in at creation.
However, Java sees that I have that list and can't nail down that all the information for my situation is available at compile time, since I could try to add things to the list later and, due to type erasure, it can't guarantee that safety. It's not really possible to communicate to Java the conditions involved in my situation without applying the generic type to the class.
I think that the simple answer is that you cannot do that. If the type of one of a classes attributes depends on a type parameter, that parameter has to be declared at the class level. And I don't think that it "makes sense" any other way.
If T in your example is not a type parameter of the class, what is it? It cannot be the type parameter of the method, because that type is determined by how the method is called. (If the method is called in different static contexts with different inferred types for T, what is the notional type of T in the context of the attribute declaration?)
So to bring this back to what you are trying to do here, an instance of MyClass will hold elements of some type, and you want to be able to insert and remove elements in a statically typesafe fashion. But at the same time you don't want to be able to say what that type is. So how is the compiler supposed to statically distinguish between a MyClass instance that holds (say) Integer objects and one that holds String objects?
I don't even think you could implement this with explicit dynamic typechecks. (I think that type erasure means that the implementation of the getSortedList() method cannot find out what actual type is bound to its return type.)
No. The real solution is to make MyClass a generic class that declares the type parameter T; e.g.
public class MyClass <T extends Comparable<T>> {
and remove the declaration of the method-level type parameter T from the two methods.
There's plenty of unchecked warnings in this, but in principle it's not necessary to keep the List as anything but something containing things you know are Comparable. You enforce the rules you need to in the constructor, and everything else should be fine. How about something like this:
public class MyClass {
final private List<Comparable> values;
public <T extends Comparable<? super T>>MyClass(T... values){
this.values = new ArrayList<Comparable>();
for(T item : values) {
this.values.add(item);
}
}
public <T extends Comparable<? super T>> List<T> getSortedLst() {
Collections.sort(this.values);
return (List<T>)this.values;
}
}
A quick test using the following shows that for classes that implement Comparable (like Integer and String) MyClass behaves as expected, but will throw a compilation error for classes that do not implement Comparable:
class Junk { }
public static void main(String[] args){
MyClass s = new MyClass(1,2,3);
System.out.println(s.getSortedLst());
MyClass a = new MyClass("c", "a", "b");
System.out.println(a.getSortedLst());
MyClass c = new MyClass(new Junk());
}
I believe the following will achieve what you want (stronger typing of Comparable). This will prevent people adding Comparable objects which are not from your interface to the list and allow multiple implementations.
public class test<T extends ComparableType> {
final List<T> values = new ArrayList<T>();
public test (T... values) {
for(T item : values) {
this.values.add(item);
}
}
public List<T> getSortedLst() {
Collections.sort(this.values);
return Collections.unmodifiableList(this.values);
}
}
public interface ComparableType extends Comparable<ComparableType> {}
public class ConcreteComparableA implements ComparableType {
#Override
public int compareTo(ComparableType o) {
return 0;
}
}
public class ConcreteComparableB implements ComparableType {
#Override
public int compareTo(ComparableType o) {
return 0;
}
}
edit:
I know this may be obvious; but if you do not wish the class to be Generic this solution will also work with:
public class test {
final List<ComparableType> values = new ArrayList<ComparableType>();
public test (ComparableType... values) {
for(ComparableType item : values) {
this.values.add(item);
}
}
public List<ComparableType> getSortedLst() {
Collections.sort(this.values);
return Collections.unmodifiableList(this.values);
}
}
Consider it like this (what I am about to say isn't reality. but it illustrates why you need to do what you need to do):
class Foo<T>
{
private T value;
T getValue() { return value; }
void setValue(T val) {value = val; }
}
// some code that uses the above class
Foo<Integer> iFoo = new Foo<Integer>();
Foo<String> sFoo = new Foo<String>();
iFoo.setValue(5);
sFoo.setValue("Hello");
When this happens the compiler (DOES NOT REALLY DO WHAT I AM ABOUT TO SAY!) generates the following code:
class IntegerFoo
{
private Integer value;
Integer getValue() { return value; }
void setValue(Integer val) {value = val; }
}
class StringFoo
{
private String value;
String getValue() { return value; }
void setValue(String val) {value = val; }
}
// some code that uses the above class
IntegerFoo iFoo = new IntegerFoo();
StringFoo< sFoo = new StringFoo();
iFoo.setValue(5);
sFoo.setValue("Hello");
If you were able to have the instance variables/methods parameterized without parameterizing the class the above thing (WHICH IS NOT REALITY!) wouldn't work.
What you are trying to do should be possible with static methods, but I don't think that is what you want.
Can you explain why you want to do the code you are trying to do? Perhaps we can figure out a better way to do what you want to do that works within the language.
I'd do it this way (I did it as a list or as an array), unless you really need the instance variable/methods:
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MyClass
{
public static <T extends Comparable<T>> List<T> asSortedList(final T ... vals)
{
final List<T> temp;
temp = new ArrayList<T>(vals.length);
temp.addAll(Arrays.asList(vals));
Collections.sort(temp);
return (Collections.unmodifiableList(temp));
}
public static <T extends Comparable<T>> T[] asSortedArray(final Class<?> clazz,
final T ... vals)
{
final T[] temp;
temp = (T[])Array.newInstance(clazz,
vals.length);
System.arraycopy(vals,
0,
temp,
0,
vals.length);
Arrays.sort(temp);
return (temp);
}
public static void main(final String[] argv)
{
final List<String> list;
final String[] array;
list = MyClass2.asSortedList("c", "a", "b");
System.out.println(list);
array = MyClass2.asSortedArray(String.class, "z", "y", "x");
System.out.println(Arrays.deepToString(array));
}
}
the type constraint you want on the variable can't be expressed directly. you can introduce a new type to bridge the problem.
static class MyList<T extends Comparable<? super T>> extends ArrayList<T>{}
final MyList<?> values;
however, there is no point to be extremely type safe in a private piece of code. Generic is there to help you clarify your types, not to obfuscate them.
public class MyClass<T extends Comparable<? super T>> {
// This doesn't work as T isn't defined
final List<T> values;
public MyClass (T... values) {
this.values = new ArrayList<T>(Arrays.asList(values));
}
public List<T> getSortedLst() {
Collections.sort(this.values);
return this.values;
}
}

Categories