In:
public class Organic<E> {
void react(E e) {
}
static void main(String[] args) {
Organic<? extends Elem> compound = new Organic<Elem>();
compound.react(new Elem());
}
}
class Elem {}
Why do I get the following compilation error?
The method react(capture#1-of ? extends Elem) in the type Organic<capture#1-of ? extends Elem> is not applicable for the arguments (Elem)
From http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
List is an example of a bounded wildcard. The ? stands for an unknown type, just like the wildcards we saw earlier. However, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard.
There is, as usual, a price to be paid for the flexibility of using wildcards. That price is that it is now illegal to write into shapes in the body of the method. For instance, this is not allowed:
public void addRectangle(List<? extends Shape> shapes) {
// Compile-time error!
shapes.add(0, new Rectangle());
}
You should be able to figure out why the code above is disallowed. The type of the second parameter to shapes.add() is ? extends Shape-- an unknown subtype of Shape. Since we don't know what type it is, we don't know if it is a supertype of Rectangle; it might or might not be such a supertype, so it isn't safe to pass a Rectangle there.
Specifically talking about your solution, you cannot call react with an object of Elem type, as with type Organic<? extends Elem> you can legally assign compound = new Organic<ElemSubClass>() - and then react will cause compile error as you cannot call it passing a super class object.
modified your method reactas per below, it will work:
void react(Elem e) {
}
The '? extends SomeClass' is used in defining generic types when you want to allow user to pass only SomeClass or it's subclasses as a generic parameter. It means you can do this:
public class Organic<E extends Elem> {
void react(E e) {
}
if you want Organic to be parametrized with subclasses of Elem. In main method you can do something like this:
Organic<Elem> compound = new Organic<ElemOrAnyElemSubclass>();
as i know there's no need to use
Organic<? extends Elem>
in method body.
Entire code:
public class Organic<E extends Elem> {
void react(E e) {
}
static void main(String[] args) {
Organic<Elem> compound = new Organic<Elem>();
compound.react(new Elem());
}
}
class Elem {}
class ElemSubClass extends Elem {} // if you need
Moreover you have to use the same generic types in both left and right part of expression. This is illehal:
Organic compound = new Organic();
Not sure it is what you wanted but hope it will help
Related
Given the following setup:
public class TestType {
public static void main(String[] args) {
List<Constants> list = new ArrayList<>();
accept(list); //Does not compile
}
static void accept(Iterable<MyInterface> values) {
for (MyInterface value : values) {
value.doStuff();
}
}
}
interface MyInterface<T> {
T doStuff();
}
enum Constants implements MyInterface<Integer> {
ONE, TWO, THREE;
#Override
public Integer doStuff() {
return ordinal();
}
}
Why won't the compiler accept the list as parameter to accept()?
List extends Iterable via Collection so that isn't the problem.
On the other hand, the compiler tells me that
incompatible types: java.util.List<enums.Constants> cannot be converted to java.lang.Iterable<enums.MyInterface>
But Constants IS a MyInterface... isn't it?
The problem is with how Generics work. Specifically, Generics are non-reified... meaning that the compiler will not see an Iterable<enum.Constants> as an Iterable<enum.MyInterface> even if Constants is a sub-class of MyInterface.
However, there is a way to get around it: Generic wildcards.
If you change static void accept(Iterable<MyInterface> values) to static void accept(Iterable<? extends MyInterface> values), it should work.
You need to use Iterable<? extends MyInterface> instead of Iterable<MyInterface> because even though Constants is a subtype of MyInterface, Iterable<Constants> is not a subtype of Iterable<MyInterface> - and I'll show you why:
If it was so (let's use List instead of Iterable for the next example), I would be able to do this:
List<Constant> constantsList = new ArrayList<Constants>(); // list of constants
List<MyInterface> ifaceList = constantsList; // you said this would be OK ...
// assume MyOtherImplementation is another implmentation of MyInterface
ifaceList.add(new MyOtherImplementation()); // OK, MyOtherImplementation implements MyInterface
Constant myConst = constantsList.get(0); // Oops! I just got an instance of MyOtherImplementation from List<Constant> - not cool.
Generic types do not inherit this way, although it may seem counter-intuitive at first glance. Using Iterable<? extends MyInterface> will allow you to use any Iterable (e.g., a List) of a type that extends MyInterface (e.g. Constants).
When defining something like this method:
class State {
public void addOperator(Operator<? extends State> op) {
}
}
Is there any way to define it in this way:
class State {
public void addOperator(Operator<? extends this.getClass()> op) {
}
}
So that any class inherting from State forces all passed in value to conform to its class-type.
I know that the above wont work, but is there anyway to force a generic wild-card to at least match the current classes type?
You already accepted an answer that claims your desired constraint can't be expressed in Java. If I understand the requirements correctly, the following solution comes close.
// You didn't flesh out what an operator does or provides,
// so I'll just make something up.
interface Operator<T> {
void apply(T arg);
}
// Request that a derived type provide its own type as a type
// parameter, per the Curiously Recurring Template Pattern (CRTP).
abstract class State<T extends State> {
public void addOperator(Operator<? extends T> op) {
final PrintStream s = System.out;
s.print("Received an operator of concrete type ");
s.print(op.getClass().getName());
s.println('.');
}
}
final class DerivedState extends State<DerivedState> {
}
public class Driver {
public static void main(String[] args) {
DerivedState ds = new DerivedState();
ds.addOperator(new Operator<DerivedState>() {
// ...
});
// And the following will not compile:
ds.addOperator(new Operator<Integer>() { /* ... */ });
}
}
Note that DerivedType's apply() method will only accept an Operator argument whose type parameter is DerivedType—or some type derived from DerivedType, but since DerivedType is final, no other such types exist.
What we can't do—which may be what Chris was alluding to—is mandate that the type parameter provided to State is in fact the derived type itself. We can't prevent the following definition, where one class supplies another as the type parameter for State:
final class AnotherDerivedState extends State<DerivedState> {
}
Here, one could call AnotherDerivedState#addOperator() with an Operator<DerivedState>, which is obviously not of type Operator<AnotherDerivedState>.
You can't prevent someone from deriving from State "incorrectly", but if you assume that people will follow the intended derivation pattern, you can help them use the rest of your library safely.
A subclass can be used instead of the superclass at any time because of the inclusion polymorphism.
Try writing
State.class
to get the Class object of State.
class State {
public void addOperator(Operator<? extends State.class> op) {
}
}
Although I am not sure that Class object inherit among them, they use generics, Class<T>.
So let's say we have class Base, and class Derived extends Base.
Class<Derived> probably does extends Class<Base>.
Instead, this scenario looks more promising
class State {
public void addOperator(Operator<Class<? extends State>> op) {
}
}
I'm following this:
http://rickyclarkson.blogspot.com/2006/07/duck-typing-in-java-and-no-reflection.html
And I'm trying to adapt this:
<T extends CanQuack & CanWalk> void doDucklikeThings(T t)
{
t.quack();
t.walk();
}
To this:
public class Activate<D extends CanQuack & CanWalk> {
D d = new MyWaterFowl(); //Type mismatch
}
Even though MyWaterFowl implements those interfaces.
I'd like a solution that never mentions MyWaterFowl in the <>'s since I'm going to eventually just be injecting it (or anything else that implements those interfaces).
If your answer is basically "You can't do that, what type would it even be?". Please explain why it's working for the method doDucklikeThings and conclusively state if it is impossible to do the same with a class or, if it is possible, how to do it.
The T in doDucklikeThings must be something valid since it's working. If I passed that into a class what would I be passing in?
As requested here's the MyWaterFowl code:
package singleResponsibilityPrinciple;
interface CanWalk { public void walk(); }
interface CanQuack { public void quack(); }
interface CanSwim { public void swim(); }
public class MyWaterFowl implements CanWalk, CanQuack, CanSwim {
public void walk() { System.out.println("I'm walkin` here!"); }
public void quack() { System.out.println("Quack!"); }
public void swim() { System.out.println("Stroke! Stroke! Stroke!"); }
}
Remember I've confirmed that doDucklikeThings works. I need the syntax that will let me inject anything that implements the required interfaces.
This does not work, because the class/method is generic and the caller of your class/method can set D to MyAmericanEagle.
Activate<MyAmericanEagle> active = new Activate<>();
Then your code would result in
MyAmericanEagle d = new MyWaterFowl();
Since that makes no sense (would result in ClassCastException) the compiler rejects it.
// Type mismatch
Even though MyWaterFowl implements those interfaces.
It's not about the type D implementing those interfaces (and/or extending a class). A generic type variable is bound to a specific type argument. That type might be completely different than MyWaterFowl so you cannot use them interchangeably.
To answer your edit, you are doing two completely different things in your two snippets. The type variable is declared with some bounds. It is therefore guaranteed to be a type that implements some interface (or extends some class), but you don't know which type that is, in either case.
I want to clarify the two things you did, ie. what you expect in your question and the solution you gave in your answer.
Generics are a compile time feature where the server code, for example
class Activate<D extends CanWalk & CanQuack> {
D instance;
public Activate(D d) {
this.instance = d;
}
public D getInstance() {
return instance ;
}
}
declares a type variable. This is a variable. Within its declaration context, you don't know its exact type at compile time.
The client code, for example,
new Activate<>(new MyWaterFowl());
binds the type MyWaterFowl to the type variable declared in Activate. So the client code knows what D is at compile time.
If the following
public D getInstance() {
D someRef = new MyWaterFowl();
return someRef;
}
was allowed in the server code, this would fail
Activate<SomeOtherBird> activate = new Activate<>(new SomeOtherBird());
SomeOtherBird reference = activate.getInstance();
Generics guarantee that getInstance() is type safe because it is declared as returning whatever type is bound to the type variable D. In this case, that is SomeOtherBird. If the getInstance() code above was allowed, type safety would be broken as getInstance() would return something other than what was bound to it.
This doesn't change the fact that within your server code (the generic class), you do know the bounds of D, ie. it is both a CanQuack and a CanWalk. Therefore, anything an object of those types can do, so can an object referenced by a D variable do.
It actually can be done.
The generic code between <>'s is fine. It's not different for methods and classes. Just needed to finish doing the dependency injection:
public class Activate<D extends CanQuack & CanWalk> {
private D d;
Activate(D d) {
this.d = d;
}
void doDuckLikeThings() {
d.quack();
d.walk();
//d.swim(); //Doesn't work
//And shouldn't since that was the whole point of ISP.
}
}
public class MainClass {
public static void main(String[] args) {
Activate<MyWaterFowl> a = new Activate<>(new MyWaterFowl());
a.doDuckLikeThings();
}
}
Thought I'd provide an answer that says what to do to fix it.
Type of class which extends Object is different with type of Object. This means you cannot instantiate super class for its extenders.
When you compile this:
1 public class Sample<T extends Object> {
2 public Sample() {
3 T t = new Object();
4 }
5 }
you got incompatible types error.
Sample.java:3: error: incompatible types
T t = new Object();
^
required: T
found: Object
where T is a type-variable:
T extends Object declared in class Sample
1 error
Its same as when you do it in non generic form:
1 public class Sample{
2 public Sample() {
3 }
4 }
5
6 class SampleExtends extends Sample {
7 public SampleExtends() {
8
9 }
10 }
11
12 class User {
13 public User() {
14 SampleExtends se = new Sample();
15 }
16 }
you get this error from compiler: incompatible types
Sample.java:14: error: incompatible types
SampleExtends se = new Sample();
^
required: SampleExtends
found: Sample
1 error
What do you expect the actual type of D to be in the second code snippet?
Let's say something does this:
Activate<Daffy> myActivate = Activate<Daffy>();
What should happen then? This means D needs to be of type Daffy but you are trying to set d to an instance of MyWaterFowl.
Generics works just the same for classes as for methods.
You seem to misunderstand Generics a bit. A type parameter <T extends CanQuack & CanWalk> is not a definition of a new type alias valid for the scope of method or class, it is a placeholder for some type, which is later filled by someone else.
For a generic method like your example
<T extends CanQuack & CanWalk> void doDucklikeThings(T t)
{
t.quack();
t.walk();
}
the caller of the method decides which type to substitute for T (within the limits stated by the bounds).
So one can use
doDuckLikeThings(myWaterfowl);
and the compiler guesses what type parameter you want here (likely the type of the myWaterfowl variable).
For a generic class, it is the code which creates an instance of the class who decides the actual type parameter.
So I can say
Activate<Duck> duckActivator = new Activate<Duck>();
After this, the duckActivator instance is an instance of Activate<Duck>, and inside it, D is now bound to Duck.
Now obviously your variable declaration says
Duck d = new MyWaterfowl();
and this doesn't work.
It wouldn't work in a generic method, either – this one is invalid just as well:
<T extends CanQuack & CanWalk> void doDucklikeThings()
{
T t = new MyWaterfowl();
}
I'd like a solution that never mentions MyWaterFowl in the <>'s since I'm going to eventually
just be injecting it (or anything else that implements those interfaces).
Then don't mention its constructor either.
Whoever is injecting your duck like object also has to decide the actual type parameter – i.e. this should be the one who creates the Activate instance. And this can't change after construction of your Activate object.
A candidate solution to the actual problem
If this restriction doesn't fit for you (e.g. because the same instance of Activate will need to be able to work with different types of duck like objects one after another), maybe a type parameter is not for you.
Maybe a generic wrapper with a wildcard type parameter for a variable helps instead.
Take this generic wrapper (or something similar):
public class Holder<T> {
private final T t;
public T get() { return t; }
public Holder(T t) { this.t = t; }
}
Then your Activate class doesn't need the type parameter, but just holds a holder variable with a wildcard type parameter. (Note that the actual Holder instantiation has a non-wildcard type argument.)
public class Activate {
private Holder<? extends CanQuack & CanWalk> holder;
public <D extends CanQuack & CanWalk> void setDuckLike(D d) {
this.holder = new Holder<D>(d);
}
public Activate() {}
public void doDucklikeThings() {
holder.get().quack();
holder.get().walk();
}
}
Now you do something like this:
Activate a = new Activate();
a.setDuckLike(new Duck());
a.doDucklikeThings();
a.setDuckLike(new MyWaterfowl());
a.doDucklikeThings();
Java is not allowing me to add a subclass of the Type declaration in this class
public class Exam<T> {
public void set(Holder<? super T> hold){
}
public T get(Holder<? extends T> holder){ return holder.get();}
public static void main (String[] args){
Exam<Question> eq = new Exam<Question>();
eq.set(new Holder<Identification>());
}
}
Where Identification is a subclass of Question.
and this how my holder class looks like
public class Holder<T> {
T item;
public void set(T item){ this.item = item; }
public T get(){return item;}
}
ERROR
The method set(Holder<? super Question>) in the type Exam<Question> is not applicable for the arguments (Holder<Identification>)
The error looks pretty self-explanatory to me - the set method expects a Holder<? super Question> and you're trying to give it a Holder of something that is a subclass of Question. As written, Exam.set could take a Holder<Object>, for example, but not a Holder<Identification>.
A good way to think about extends and super in generics is in terms of assignment: T extends Foo will accept any type T that you could use on the right hand side of an assignment to Foo without casting, i.e.
Foo something = new T();
(treat this as pseudocode - I know you're not really allowed to new a type varaible). Conversely, T super Foo accepts any T you could use on the left hand side of an assignment without casting:
T myThing = new Foo();
In your specific example, Identification i = new Question() isn't legal without a cast, so a Holder<? super Question> parameter can't accept a Holder<Identification> value.
Exam<T> expects a Holder<T> that can hold any subclass of T. That's what the super does. You are passing a Holder<Identification> but Identification is neither T nor a superclass of it.
change set method of class Enum to
public void set(Holder<? extends T> hold){
}
Generic is invariant. That could be an answer for you. Invariant means that Type2 is a subclass of Type1 so it doesn't mean that List is a List.
It works (but has a different meaning, of course) if you write
public void set(Holder<? extends T> hold){ }
Given the interface:
public interface BasedOnOther<T, U extends BasedList<T>> {
public T getOther();
public void staticStatisfied(final U list);
}
The BasedOnOther<T, U extends BasedList<T>> looks very ugly in my use-cases. It is because the T type parameter is already defined in the BasedList<T> part, so the "uglyness" comes from that T needs to be typed twice.
Problem: is it possible to let the Java compiler infer the generic T type from BasedList<T> in a generic class/interface definition?
Ultimately, I'd like to use the interface like:
class X implements BasedOnOther<Y> {
public SomeType getOther() { ... }
public void staticStatisfied(final Y list) { ... }
} // Does not compile, due to invalid parameter count.
Where Y extends BasedList<SomeType>.
Instead:
class X implements BasedOnOther<SomeType, Y> {
public SomeType getOther() { ... }
public void staticStatisfied(final Y list) { ... }
}
Where Y extends BasedList<SomeType>.
Update: ColinD suggested
public interface BasedOnOther<T> {
public T getOther();
public void staticSatisfied(BasedList<T> list);
}
It is impossible to create an implementation such as:
public class X implements BasedOnOther<SomeType> {
public SomeType getOther() { ... }
public void staticStatisfied(MemoryModel list);
} // Does not compile, as it does not implement the interface.
Where MemoryModel extends BasedList<SomeType>, which is needed (as it provides other methods).
It looks as if you don't actually need the type parameter U extends BasedList<T>, if you don't actually need to do anything in the class that requires some specific subclass/implementation of BasedList<T>. The interface could just be:
public interface BasedOnOther<T> {
public T getOther();
public void staticSatisfied(BasedList<T> list);
}
Edit: Based on your update, I don't think there's any way you can do this. I think you'll have to either just go with your original declaration or make some intermediate type that specifies T, like:
public interface BasedOnSomeType<U extends BasedList<SomeType>>
extends BasedOnOther<SomeType, U>
{
}
public class X implements BasedOnSomeType<MemoryModel> { ... }
That seems like kind of a waste though, and I don't really think the original declaration looks that bad.
What about this?
public interface BasedOnOther<T> {
public T getOther();
public <U extends BasedList<T>> void staticStatisfied(final U list);
}
ColinD is almost correct. What you probably want is this:
public interface BasedOnOther<T> {
public T getOther();
public void staticSatisfied(BasedList<? extends T> list);
}
That's because method arguments are covariant but the generics are invariant. Look at this example:
public test() {
Number n1;
Integer n2; //Integer extends Number. Integer is a more-specific type of Number.
n1 = n2; //no problem
n2 = n1; //Type mismatch because the cast might fail.
List<Number> l1;
List<Integer> l2;
List<? extends Number> l3;
l1 = l3; //No problem.
l1 = l2; //Type mismatch because the cast might fail.
}
Why:
Trying to put an Integer where a Number belongs is covariance and it's usually correct for function arguments.
Trying to put a Number where an Integer belongs is the opposite, contravariance, and it's usually correct for function return values. For example, if you defined a function to return a Number, it could return an Integer. If you defined it to return an Integer, however, you couldn't return a Number because that might be a floating-point, for example.
When you're dealing with generics, the compiler can't tell if the generic parameter (in your case, T) is going to be covariant or contravariant. In your code, for example, T is once a return value and once part of an argument. For that reason, generic parameters are invariant by default.
If you want covariance, use <? extends T>. For contravariance, use <? super T>. As a rule of thumb, you probably always want to specify the covariance/contravariance on all public functions. For private functions it doesn't matter as much because you usually already know the types.
This isn't specific to java, other object-oreiented languages have similar issue.
I recently had a very similar problem.
I would suggest, if you are do not need to specifically refer to MemoryModel, i.e. if U extends BasedList<T> is enough, then I would definitely do what Pepe answered.
However, if you must type check for at least two methods that both methods must use MemoryModel specifically and the type inferencing in Pepe's answer is not enough, then the only way to make the use of the clumsy/verbose parameterized constructor more simplistic, is to exploit the generic method parameter inferencing. You would need to create generic static factory methods for each constructor, where the factory methods do the type inferencing (constructors can't type inference in Java).
How to do this is covered in
Effective Java, by Joshua Block; Item 27: Favor generic methods
I also explained this and quoted the solution (with code) here.