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; }
}
Related
There's not much to add to my question, basically:
class A {}
interface I {}
// how can I get a Set<> of object of type A that implements I?
I tried a few things <A & I>, <A extends I>, <? super A extends I> and a few other but didn't find anything that works, so I'm wondering if this is possible at all. If it isn't I'm curious about the reasoning behind it.
Thanks
Java does not support intersection types, it only supports multiple bounds (as in extends A & I) when declaring type parameters. That is, we can not use a notation like A & I to denote the family of types that extend both A and I, but we can declare a type parameter <T extends A & I> to refer to a specific such type.
If the latter is what you want, a type parameter is a great fit. But if your collection should admit unrelated subtypes of A and I, no nice solutions seem to exist. My best idea is a hack like:
class AISetWrapper {
Set<A> set = new HashSet<>();
<T extends A & I> Set<T> getSet() {
return (Set<T>) set; // unchecked cast that only works because generics are not reified
}
}
which would allow us to write:
class AI1 extends A implements I { }
class AI2 extends A implements I { }
public static void main(String[] args) {
AISetWrapper aiSet = new AISetWrapper();
aiSet.get().add(new AI1()); // compiles
aiSet.get().add(new AI2()); // compiles
aiSet.get().add(new A()); // does not compile
aiSet.get().add(new I() {}); // does not compile
}
You'll have to make A implement I:
interface I {}
class A implements I {}
Set<A> setOfA;
Possible is alsp
class SubA extends A implements I { }
Set <SubA> setOfSubA;
Usage of a class A cannot make it change it's behaviour, as would be indicated by its sudden "implmentation" of I. Where should the implementations of the interface methods come from?
I was able to do the following:
public class MyClass<T extends String & Iterable>{
private Set<T> mySet;
}
And
public <T extends String & Iterable> void myFancyMethod(Set<T> mySet){}
However when I did
private Set<? extends String & Iterable>
I got a compile error of Syntax error on token "&". Seems that you can do the & syntax when declaring a type <T> but not for wildcards <? ...>.
A better discussion of this can be found at: Java Generics Wildcarding With Multiple Classes
You can write your own class:
public class MySet<E extends A & I> extends HashSet<E> {
// blank
}
This will simply ensure that any instances of MySet will contain only objects that extend A and implement I.
// how can I get a Set<> of object of type A that implements I?
You cannot guarantee both in a single generic statement. You can do something like
public void addToSet(I iInstance) {
if(iInstance instanceof A){
//logic to add to your set
}
}
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 ran into a problem when trying to specialize a class that implements a generic interface where I wanted to inherit from the same interface as the super class, but with a more specific type argument. The following snippet shows a synthetic but complete example that cannot be compiled. The comment contains the error message from the Java compiler.
interface Producer<T> {
T get();
}
class NumberProducer implements Producer<Number> {
#Override
public Number get() { return null; }
}
// Producer cannot be inherited with different arguments: <java.lang.Integer> and <java.lang.Number>
class IntegerProducer extends NumberProducer implements Producer<Integer> {
#Override
public Integer get() { return null; }
}
In the PECS sense, Producer<T> is a producer, so Producer<Integer> would be a subtype of Producer<Number>, but there's no way to declare that in the definition of Producer<T>. Java does not allow IntegerProducer to inherit from NumberProducer and Producer<Integer> at the same time as IntegerProducer would then inherit from Producer<Integer> and Producer<Number> at the same time.
Is there a standard approach to this limitation, e.g. a pattern that solves the same problem without requiring this kind of inheritance?
Just add a parameter to the super class:
interface Producer<T> {
T get();
}
class NumberProducer<T extends Number> implements Producer<T> {
#Override
public T get() { return null; }
}
class IntegerProducer extends NumberProducer<Integer> { // Implicit: implements Producer<Integer>
#Override
public Integer get() { return null; }
}
Say we had a simple Method gimme.
public static <T> T gimme(Producer<T> p) { return p.get(); }
Within the context of gimme nothing is known about T. It could be Number, Integer or any other reference type. So, due to erasure, the compiler emits an interface call to Producer.get()Object rather than the specific call to, say, IntegerProducer.get()Integer. All types that implement Producer<T> with T != Object also implicitly implement Producer.get()Object. This implicit implementation forwards to the specific implementation. That might be NumberProducer.get()Number or IntegerProducer.get()Integer, but not both. That's why you can't implement the same interface twice.
Other languages allow this via definition site variance, where Producer<Integer> is a subtype of Producer<Number>, but alas, Java does not. The common workaround is to make NumberProducer generic as well.
If you want to ensure that T is of a specific subtype you can use
interface Producer<T extends Number>
Not sure what Producer reall is so I have to guess.
Update:
If I understand you correct then I would say, you need to declare an interface which is a Producer. That's simple.
From this interface i would derive a new interface with the respecitve base type.
i.e.:
interface Producer
{
base functions
};
interface Newproducer<T extends Producer>
{
};
Is this what you had in mind?
So, say I have a simple enum and a class that uses it:
enum ThingType { POTATO, BICYCLE };
class Thing {
public void setValueType(ThingType value) { ... }
public ThingType getValueType() { ... }
}
But, in reality, I have lots of different classes that implement setValueType, each with a different kind of enum. I want to make an interface that these classes can implement that supports setValueType and getValueType using generics:
interface ValueTypeable {
public Enum<?> getValueType(); // This works
public <T extends Enum<T>> setValueType(T value); // this fails horribly
}
I can't change the class model because the classes are auto-generated from an XML schema (JAXB). I feel like I'm not grasping enums and generics combined. The goal here is that I want to be able to allow a user to select from a list of enums (as I already know the type at runtime) and set the value in a particular class.
Thanks!
Have you tried parameterizing the interface itself. Like:
class Thing<E extends Enum<? extends E>> {
public E getValueType();
public void setValueType(E value);
}
Then you have the subclass extend the one with right type:
class SomeSubClass implements Thing<ThingType> { ... }
enums are for when you have a fixed set of them. When you say that each implementation has its own, then you no longer have a fixed set, and how you are trying to use enums doesn't match your needs.
You might be interested in the request for Java to be able to have abstract enums.
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.