public static void main(String[] args) {
List<? extends Object> mylist = new ArrayList<Object>();
mylist.add("Java"); // compile error
}
The above code does not allow you to add elements to the list and wild cards can only be used as a signature in methods, again not for adding but only for accessing.
In this case what purpose does the above fulfil ??
Let's say you have an interface and two classes:
interface IResult {}
class AResult implements IResult {}
class BResult implements IResult {}
Then you have classes that return a list as a result:
interface ITest<T extends IResult> {
List<T> getResult();
}
class ATest implements ITest<AResult> {
// look, overridden!
List<AResult> getResult();
}
class BTest implements ITest<BResult> {
// overridden again!
List<BResult> getResult();
}
It's a good solution, when you need "covariant returns", but you return collections instead of your own objects. The big plus is that you don't have to cast objects when using ATest and BTest independently from the ITest interface. However, when using ITest interface, you cannot add anything to the list that was returned - as you cannot determine, what object types the list really contains! If it would be allowed, you would be able to add BResult to List<AResult> (returned as List<? extends T>), which doesn't make any sense.
So you have to remember this: List<? extends X> defines a list that could be easily overridden, but which is read-only.
In his book great 'Effective Java' (Second Edition) Joshua Bloch explains what he calls the producer/consumer principle for using generics. Josh's explaination should tell you why your example does not work (compile) ...
Chapter 5 (Generics) is freely available here: http://java.sun.com/docs/books/effective/generics.pdf
More information about the book (and the author) are available: http://java.sun.com/docs/books/effective/
With java generics using wildcards, you are allowed the above declaration assuming you are only going to read from it.
You aren't allowed to add/write to it, because all generic types must be stripped at compile time, and at compile time there isn't a way the compiler knows List are only strings, (it could be any object including strings!)
You are however allowed to read from it since they are going to be at least objects. Mixing different types are not allowed in java collections to keep things clean and understandable, and this helps ensure it.
The point of bounded wildcard types is their use in method signatures to increase API flexibility. If, for example, you implement a generic Stack<E>, you could provide a method to push a number of elements to the stack like so:
public void pushAll(Iterable<? extends E> elements) {
for(E element : elements){
push(e);
}
}
Compared to a pushAll(Iterable<E> elements) signature without a wildcard, this has the advantage that it allows collections of subtypes of E to be passed to the method - normally that would not be allowed because an Iterable<String> is, somewhat counterintuitively, not a subclass of Iterable<Object>.
This works:
List<? super Object> mylist = new ArrayList<Object>();
mylist.add("Java"); // no compile error
From O'Reilly's Java Generics:
The Get and Put Principle: use an extends wildcard when you only get values our of a structure, use a super wildcard when you only put values into a structure, and don't use a wildcard you both get and put.
List<? extends Object>, which is the same as List<?>, fulfills the purpose of generalizing all types List<String>, List<Number>, List<Object>, etc. (so all types with a proper type in place of the ?). Values of all of these types can be assigned to a variable of type List<?> (which is where it differs from List<Object>!).
In general, you cannot add a string to such a list. However, you can read Object from the list and you can add null to it. You can also calculate the length of the list, etc. These are operations that are guaranteed to work for each of these types.
For a good introduction to wildcards, see the paper Adding Wildcards to the Java Programming Language. It is an academic paper, but still very accessible.
Java Generics : Wild Cards in Collections
extends
super
?
Today I am going to explain you how the wild cards are useful. To understand this concept is bit difficult
Now Suppose you have abstract class and in that you have abstract method called paintObject().
Now you want to use different type of collection in every child class.
This below is AbstractMain Method.
Here Steps we have taken for this Abstract Main method
1. We have created abstract class
2. In Parameter we have define T(you can use any character)
--In this case whichever class implement this method it can used any type of class.
ex. Class can implement method like
public void paintObject(ArrayList object) or public void paintObject(HashSet object)
3. And We have also used E extends MainColorTO
-- In this case E extends MainColorTo
-- It's clearly means whichever class you want to use that must be sub class of MainColorTo
4. We have define abstract method called paintObject(T object,E objectTO)
--Now here whichever class is implement method that method can use any class on first argument and second parameter that method has to use type of MainColorTO
public abstract class AbstractMain<T,E extends MainColorTO> {
public abstract void paintObject(T Object,E TO);
}
Now we will extend above abstract class and implement method on below class
ex.
public class MainColorTO {
public void paintColor(){
System.out.println("Paint Color........");
}
}
public class RedTO extends MainColorTO {
#Override
public void paintColor() {
System.out.println("RedTO......");
}
}
public class WhiteTO extends MainColorTO {
#Override
public void paintColor() {
System.out.println("White TO......");
}
}
Now we will take two example.
1.PaintHome.java
public class PaintHome extends AbstractMain<ArrayList, RedTO> {
#Override
public void paintObject(ArrayList arrayList,RedTO red) {
System.out.println(arrayList);
}
}
Now in above PaintHome.java you can check that we have used ArrayList in first argument(As we can take any class) and in second argument we have used RedTO(Which is extending MainColorTO)
2.PaintCar.java
public class PaintCar extends AbstractMain<HashSet, WhiteTO>{
#Override
public void paintObject(HashSet Object,WhiteTO white) {
System.out.println(Object);
}
}
Now in above PaintCar.java you can check that we have used HashSet in first argument(As We Can take any class) and in second argument we have used WhiteTO(Which is extending MainColorTO)
Ponint to Remember
You can not use super keyword at class level you can only use extends keyword at class level defination
public abstract class AbstractMain<P,E super MainColorTO> {
public abstract void paintObject(P Object,E TO);
}
Above code will give you compiler error.
Related
I have a number of abstract classes each superclassing three or four concrete ones and of the form:
public abstract class TypeOfMapObject extends IrrelevantClass implements Serializable, MapObject, Comparable<MapObject>
{
//irrelevant stuff
#Override
public int compareTo(MapObject m)
{
//specific algorithm for natural ordering
}
}
Elsewhere in my code I have an ArrayList<MapObject> (which is being populated correctly, I have checked that) called tempMapObjectsArray I want to sort that ArrayList using Collections.sort(tempMapObjectsArray) (or, rather, I want to sort that ArrayList and it seems Collections.sort() is the best way to do it. The specific way its sorted isn't important).
It's not compiling and giving the message (in Netbeans):
no suitable method found for sort(java.util.ArrayList<Model.MapObject>)
method java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>) is not applicable
(cannot instantiate from arguments because actual and formal argument lists differ in length)
method java.util.Collections.<T>sort(java.util.List<T>) is not applicable
(inferred type does not conform to declared bound(s)
inferred: Model.MapObject
bound(s): java.lang.Comparable<? super Model.MapObject>)
It seems that I am defining the generic wrong in the TypeOfMapObject class, but this is the first time I have really used generics and it's reached the stage where I am simply trying things more or less at random. I'm reading through the tutorial but so far it's simply not "clicking" what I'm doing wrong.
EDIT: Each of the subclasses of the various abstract classes need to be comparable to each other - so if I have abstract classes TypeofMapObject1, TypeOfMapObject2 etc, then I need to be able to compare a subclass of 1 to a subclass of 2.
Match the Comparable type with the class:
public abstract class TypeOfMapObject extends IrrelevantClass implements Serializable, MapObject, Comparable<TypeOfMapObject> {
#Override
public int compareTo(TypeOfMapObject m)
{
//specific algorithm for natural ordering
}
}
Or simply don't define the compareTo method in your abstract class - leave it for the subclass to implement.
To address edit to question:
If you want to compare different subtypes, have them implement a method that returns a value (say String) with which they may be compared. For example:
public abstract class TypeOfMapObject extends IrrelevantClass implements Serializable, MapObject, Comparable<TypeOfMapObject> {
#Override
public int compareTo(TypeOfMapObject m)
{
return compareValue().compareTo(m.compareValue());
}
// subclasses to return their value to compare
protected abstract String compareValue();
}
The type returned from the compareValue() can be anything compareable, eg Integer, Date, whatever.
Ideally, it would look like this (the context doesn't matter):
public interface myInterface extends Iterable<Point>, Iterable<Segment> { ... }
But this is not allowed in Java. How can I achieve this behaviour?
Unfortunately you cannot. In Java you cannot have two methods with following signatures:
Iterator<Point> iterator();
Iterator<Segment> iterator();
in one class or interface.
As other said before, this is impossible. Better use delegation instead of multiple implementation like this:
public interface MyInterface {
Iterable<Point> points();
Iterable<Segment> segments();
}
So you can iterate using for:
MyInterface my = ...;
for (Point p : my.points()) {
...
}
for (Segment s : my.segments()) {
...
}
You cannot. Due to type erasure, in the bytecode, and therefore at run time, Iterable<Whatever> becomes Iterable.
So, at run time, your class' prototype would be:
public interface myInterface extends Iterable, Iterable { ... }
Considering that, how do you determine what class was meant to be iterated over?
As a possible workaround, you could create interfaces for the iterations you want.
public interface SegmentIterable{
public Iterator<Segment> segmentIterator();
}
public interface PointIterable{
public Iterator<Point> pointIterator();
}
It's not ideal, but would be passable as long as you had a limited number of things you wanted to iterate over.
Others have said it is impossible. They are wrong. It is possible, but probably not what you want.
public interface MyInterface<T extends Point & Segment> extends Iterable<T>
{
}
If what you are iterating extends both point and segment this will work. Otherwise Type Erasure means this won't work.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.5
A class may not at the same time be a subtype of two interface types which are different invocations of the same generic interface (ยง9.1.2), or a subtype of an invocation of a generic interface and a raw type naming that same generic interface, or a compile-time error occurs.
Instead of inheriting from the iterable types, try something like this:
public interface MyInterface {
public Iterable<Point> asPoints() { ... }
public Iterable<Segment> asSegments() { ... }
}
Then when you want to iterate, it's simply a matter of:
for (Point p : myClass.asPoints()) {
...
}
This is a pretty common practice, as seen in the Java Collections class.
You can also consider creating common interface, superclass or wrapper for Point and Segment and use it as a generic parameter.
I've got problem in my code in Java. I have four(important) Classes:
public class RDOutput extends OutputType
public class RDAnalysis extends AnalysisProperties
Now I'm trying to make a method in Analysis properties:
public abstract void display(ArrayList<? extends OutputType> results);
The main problem list, the objects in the ArrayList will be different subtypes of OutputType. In my class RDAnalysis I try to make specific overriding:
public void display(ArrayList<RDOutput> results) {
but eclipse says: Name clash: The method display(ArrayList) of type RDAnalysis has the same erasure as display(ArrayList? extends OutputType) of type AnalysisProperties but does not override it
I'm not familiar with Java tricks, I tried searching in documentation and I didn't find any solution to this problem.
My question is: Is that trick that I'm doing (Basic type in abstract and Extended in final function) possible in Java (if yes, how can I do that?) or do I have to make some enum to solve this?
I suggest you to introduce generic parameter to your class and use it to parametrize your method:
public abstract class A<T extends OutputType> {
public abstract void display(ArrayList<T> results);
}
public class B extends A<RDOutput> {
public void display(ArrayList<RDOutput> results) {}
}
It's because your display doesn't cover every case of the abstract method. Maybe try something like this :
public class RDOutput extends OutputType {}
public class OutputType {}
public abstract class AnalysisProperties<T extends OutputType> {
public abstract void display(ArrayList<T> results);
}
public class RDAnalysis extends AnalysisProperties<RDOutput> {
#Override
public void display(final ArrayList<RDOutput> results) {
}
}
The problem is that you try to override a method while restricting possible parameters.
=> ArrayList<? extends OutputType> accepts more possible elements than ArrayList<RDOutput> since RDOutput extends OutputType.
You break the rule that says: the concerned subclass method has to encompass at least elements of superclass one and NEVER restrict them.
So compiler avoid to valid this override.
By the way, avoid to type your reference with concrete values like ArrayList.
What about a LinkedList passed as arguments? ... prefer a more generic relevant type like List.
Problem here is that, after type erasure comes into play, the signature of the two methods are undistinguishable: they have the same return type and they can both accept a ArrayList<RDOutput> but the first one (the generic one) can also accept any ArrayList<T extends OutputType>.
This mean that, although the JVM won't be able to choose which one to call at runtime if you pass an ArrayList<RDOutput>, at the same time your display method does not override the abstract one because your method only work for lists of RDOutput, so if you pass a List<T extends OutputType> with T != RDOutput your specific implementation doesn't accept it.
You should consider using a type parameter on the whole class as suggested in other answers, or accept the fact that you won't be able to use any RDOutput specific methods in your display method without a cast.
if a method is expecting ArrayList<? extends OutputType>
ArrayList<RDOutput> cannot be passed to it, as parent type allows any child class of OutputType in arraylist.
consider a code like this
AnalysisProperties properties = new RDAnalysis();
properties.display(arraylist consisting of any child class of OutputType); //this line will cause runtime problems
I want to define an interface MyList which is a list of interface MyThing. Part of the semantics of MyList is that its operations don't have any meaning on objects which do not implement the MyThing interface.
Is this the right declaration?
interface MyList<E extends MyThing> extends List<E> { ... }
edit: (part 2) Now I have another interface that returns a MyList as one of its methods.
// I'm defining this interface
// it looks like it needs a wildcard or template parameter
interface MyPlace {
MyList getThings();
}
// A sample implementation of this interface
class SpecificPlace<E extends MyThing> implements MyPlace {
MyList<E> getThings();
}
// maybe someone else wants to do the following
// it's a class that is specific to a MyNeatThing which is
// a subclass of MyThing
class SuperNeatoPlace<E extends MyNeatThing> implements MyPlace {
MyList<E> getThings();
// problem?
// this E makes the getThings() signature different, doesn't it?
}
Yes, at least that is how EnumSet does it.
public abstract class EnumSet<E extends Enum<E>>
extends AbstractSet<E>
Edit in answer to Part 2:
I'm not sure why the return type of getThings() in the interface doesn't complain about raw types. I suspect that because of type erasure, warnings in interfaces would be useless even if they were there (there's no warning if you change the return type to List, either).
For the second question, since MyNeatThing extends MyThing, E is within its bounds. That's sort of the point of using the extends bound in the generic parameter, isn't it?
For part 1, yes that looks right.
For your part 2, I suggest something like the following. The method returns a MyList of something, which you don't know what it is (it is different for different implementations apparently), but you know it's a subtype of MyThing.
interface MyPlace {
MyList<? extends MyThing> getThings();
}
Keep in mind that implementing interfaces like java.util.List correctly is hard; so ask yourself all of these questions:
Can I use java.util.List "as is", do
I need to add/remove functionality?
Is there something simpler I could implement, like Iterable<T>?
Can I use composition? (vs. inheritance)
Can I find the
newly desired functionality in
existing libraries like Google
Collections?
If I need to
add/remove functionality, is it worth
the added complexity?
That said, you could probably just use java.util.List for your example:
interface MyPlace<T extends MyThing> {
List<T> getThings();
}
class SpecificPlace implements MyPlace<MyThing> {
public List<MyThing> getThings() { return null; }
}
class SuperNeatoPlace implements MyPlace<MyNeatThing> {
public List<MyNeatThing> getThings() { return null; }
}
I have an abstract Class Monitor.java which is subclassed by a Class EmailMonitor.java.
The method:
public abstract List<? extends MonitorAccount> performMonitor(List<? extends MonitorAccount> accounts)
is defined in Monitor.java and must be overridden in EmailMonitor.java.
I currently have the method overridden in EmailMonitor.java as follows:
#Override
public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
//...unrelated logic
return emailAccounts;
}
However, this produces the compile time error:
Name clash: The method performMonitor(List<EmailAccount>) of type EmailMonitor has the same erasure as performMonitor(Lis<? extends MonitorAccount> emailAccounts) of type Monitor but does not override it
EmailAccount is a subclass of MonitorAccount, so (in my mind at least) overriding it in this way makes perfect sense. Seeing as the compiler is not happy with my logic though, How should I go about this correctly while still keeping my compile time checks to make sure that all calls to EmailMonitor.performMonitor() receive Lists of EmailAccount rather than some other type of MonitorAccount?
No, it's not overriding it properly. Overriding means you should be able to cope with any valid input to the base class. Consider what would happen if a client did this:
Monitor x = new EmailMonitor();
List<NonEmailAccount> nonEmailAccounts = ...;
x.performMonitor(nonEmailAccounts);
There's nothing in there which should give a compile-time error given your description - but it's clearly wrong.
It sounds to me like Monitor should be generic in the type of account it can monitor, so your EmailMonitor should extend Monitor<EmailAccount>. So:
public abtract class Monitor<T extends MonitorAccount>
{
...
public abstract List<? extends T> performMonitor(
List<? extends T> accounts);
}
public class EmailMonitor extends Monitor<EmailAccount>
{
#Override
public abstract List<? extends EmailAccount> performMonitor(
List<? extends EmailAccount> accounts)
{
// Code goes here
}
}
You might want to think carefully about the generics in the performMonitor call though - what's the return value meant to signify?
Here is my own solution. I suspect this is the same thing Jon Skeet was trying to get at... without the typo (see my comment in reply to his answer).
the Monitor.java class:
public abstract class Monitor <T extends MonitorAccount> {
...
public abstract List<T> performMonitor(List<T> accounts);
..
}
EmailMonitor.java
public class EmailMonitor extends Monitor<EmailAccount> {
...
public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
..//logic...logic...logic
return emailAccounts;
}
...
}
In this configuration, EmailMonitor.performMonitor() will always check at compile time that it receives a list of EmailAccount rather than any of my other types FTPAccount, DBAccount, etc... It's much cleaner than the alternative, which would have been receiving/sending a raw list and then having to coerce it the required type resulting in potential runtime type casting exceptions.