Given the following type signatures, I'm able to compile and run the code under Maven with both JDK 6 and JDK 7, but Eclipse gives a "Bound mismatch: The type F is not a valid substitute for the bounded parameter <F extends Field<TP,F>> of the type Field<TP,F>" error in TupleVisitor.
I believe I need these types, although I understand this is difficult to motivate given the stripped-down example. Can anyone suggest a workaround that will let me continue to work in Eclipse?
public abstract class Tuple<F extends Field<TP, F>, TP extends Tuple<F, TP>>
public class VariableTuple<F extends Field<VariableTuple<F>, F>> extends Tuple<F, VariableTuple<F>>
public class ConstantTuple<F extends Field<ConstantTuple<F>, F>> extends Tuple<F, ConstantTuple<F>>
public class Field<TP extends Tuple<F, TP>, F extends Field<TP, F>>
public class ConstantField extends Field<ConstantTuple<ConstantField>, ConstantField>
public class VariableField extends Field<VariableTuple<VariableField>, VariableField>
public interface TupleVisitor {
public <F extends Field<VariableTuple<F>, F>> void visit(VariableTuple<F> tuple, F field); //Eclipse error
public <F extends Field<ConstantTuple<F>, F>> void visit(ConstantTuple<F> tuple, F field); //Eclipse error
}
Filed bug at: https://bugs.eclipse.org/bugs/show_bug.cgi?id=422503
No simple workaround identified. While Rohit Jain's answer wouldn't work with a visitor pattern, I took his follow-up advice and removed F as a type parameter from Field.
This seems to a be a bug with eclipse, as it is compiling fine under javac for me too. In fact, there are few bugs related to self-referential Java generics related to eclipse that I found, but this isn't there. So, may be you should file one.
As for a workaround of this, I just found one, which I doubt you would like, as you have to make your interface generic. Yes, you heard it right. Declaring the type parameters with the interface itself, makes the code compile fine. Here's the compiling code:
interface TupleVisitor<E extends Field<VariableTuple<E>, E>,
F extends Field<ConstantTuple<F>, F>> {
void visit(VariableTuple<E> tuple, E field);
void visit(ConstantTuple<F> tuple, F field);
}
Of course there are two type variables, as the bounds on both of them are different. Check if this suits your need, because this really sounds to be as weird work-around, as the number of type parameters depends on the total number of implementors of Tuple class (Actually weird, isn't it?). Or else you have to do some other changes.
The problem likely is that type parameters are provided by the caller. Given your declarations, somebody could declare
class ReallyConstantField extends ConstantField {}
and then invoke TupleVisitor.visit while providing ReallyConstantField for F. The visit method's type constraint would then read
ReallyConstantField extends Field<ConstantTuple<ReallyConstantField>, ReallyConstantField>
so we use a ConstantTuple<ReallyConstantField>. The type constraint for that class would then read
ReallyConstantField extends Field<ConstantTuple<ReallyConstantField>, ReallyConstantField>
which is incorrect, as ReallyConstantField is a ConstantField which is a Field<ConstantTuple<ConstantField>, ConstantField>, which is an inconvertible type.
That is, even though you declare a type parameter with an extends bound, the only valid type argument is a single type. That is, you don't need a type parameter at all, but could simply declare:
void visit(ConstantTuple<ConstantField> tuple, ConstantField field);
Update
BTW, if these are supposed to be, as the example suggests, parallel class hierarchies with a one-to-one correspondence between the classes of different hierarchies, there is a simpler way to write the generics:
abstract class Tuple<F extends Field<TP, F>, TP extends Tuple<F, TP>> {}
class VariableTuple extends Tuple<VariableField, VariableTuple> {}
class ConstantTuple extends Tuple<ConstantField, ConstantTuple> {}
class Field<TP extends Tuple<F, TP>, F extends Field<TP, F>> {}
class ConstantField extends Field<ConstantTuple, ConstantField> {}
class VariableField extends Field<VariableTuple, VariableField> {}
interface TupleVisitor {
public void visit(VariableTuple tuple, VariableField field);
public void visit(ConstantTuple tuple, ConstantField field);
}
Related
I am trying to call the Enum<E> class's static method valueOf() but I received a compile error.
Please look at the code snippet below.
public void hello(Class<? extends Enum<?>> q){
Object o= Enum.valueOf(q,"hello");
}
IntelliJ IDEA complies the following code just fine, but Eclipse gives a compile error:
I don't know IntelliJ's workings, but I can tell you the reason why it doesn't compile.
The method defined in the class Enum<T extends Enum<T>>
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
has a first argument that is the class of a type T which is defined by T extends Enum<T>. That is, it extends an enumeration type with the same generic type as itself.
When you call the method with the first argument as
Class<? extends Enum<?>>
you are not specifying that the two ? are in fact the same type, as required. This throws the mismatch error.
What you can do with your method is turn it generic:
public static <E extends Enum<?>> void hello(Class<E> q)
but as you can imagine, this will still not compile because ? is not necessarily E. So you need to spell it out:
public static <E extends Enum<E>> void hello(Class<E> q)
and this will compile.
Edit: another way to think about it
You could think of fixing your method signature
public void hello(Class<? extends Enum<?>> q)
by changing it to
public void hello(Class<E extends Enum<E>> q)
just to specify that the two wildcards are the same. The concept is right, but the syntax is not legal. You must define what E is (either by making your method generic or your class).
I want to parametirize class with two other params, so that I can provide one of them independently, AdGroupIdentifier OR KeywordIdentifier. But I am getting following warning: The type parameter KeywordIdentifier is hiding the type KeywordIdentifier.
Do you think I am doing something wrong? What is a correct way of doing that?
Thanks for any help!
public class Metrics <T extends AdGroupIdentifier, KeywordIdentifier> {
public void addMetric(T identifier){ .... }
}
It seems that you have class named KeywordIdentifier. The class parameter named KeywordIdentifier does not relate to class with the same name but can confuse humans. This is exactly what the compilation warning mean.
BTW according to naming convention you should tend to call type parameter using one (or maximum 2) capital letter. In your case change the class definition to
public class Metrics <T extends AdGroupIdentifier, K>
or, if you want the seconds parameter to extend class KeywordIdentifier:
public class Metrics <T extends AdGroupIdentifier, K extends KeywordIdentifier>
Just remove the KeywordIdentifier. It seems that AdGroupIdentifier implements or extends KeywordIdentifier:
public class Metrics <T extends AdGroupIdentifier> {
public void addMetric(T identifier){ .... }
}
Normally generic types are given one letter names as they are parameterized.
The way you have it, you might confuse KeywordIndetifier which extends Object with your class KeywordIdentifer and while they have the same name, they are not related.
I have a very specific problem with java generics. The follwowing classes and interfaces have been predefined:
public interface IFirst<R, T> {...}
public abstract class AbstractFirst<T extends AbstractFirst, L extends IFirst<String, T>> {...}
public interface ISecond extends IFirst<String, AbstractSecond> {...}
public abstract class AbstractSecond extends AbstractFirst<AbstractSecond, ISecond> {...}
Now I've created a following repo definition which seems to be valid:
public abstract class AbstractRepo<T extends AbstractFirst<T, IFirst<String,T>>> {...}
But now that i want to extend it:
public class RepoFirst extends AbstractRepo<AbstractSecond> {...}
I get the following error:
Bound mismatch: The type AbstractSecond is not a valid substitute for the bounded parameter
<T extends AbstractFirst<T,IFirst<String,T>>> of the type AbstractRepo<T>
I cannot change the first four (at least not radically) beacuse they are too heavily ingrained with the rest of the application, but the second two are new and up for change if need be.
Also intrestingly it allows the following (with raw type warnings):
public class RepoFirst extends AbstractRepo {
...
#Override
AbstractFirst someAbstractMethod() {
return new AbstractSecond() {...};
}
...
}
But for code clarity I would like to implement it with clearly defining AbstractSecond as the generic type for Abstract Repo.
What am I missing?
Your AbstractRepo expects an instance of IFirst and not a subtype of IFirst. But your AbstractSecond is clearly not IFirst. (I mean it is, from a OO standpoint but for generics, List<Number> is not the same as List<Integer>). It's ISecond. It might work if you could change your AbstractRepo from IFirst to ? extends IFirst as you did for AbstractFirst.
I have the following sets of classes:
public abstract class GSObject<T extends GSObject<T>> {
public abstract boolean matches(String toMatch);
//Other functions
public static <T extends GSObject<T>> T findMatch(List<T> objects, String toMatch){
//Code that iterates through the list, seeing if one matches;
}
}
public abstract class Phrase extends GSObject<Phrase> {
//More code
}
public class Request extends Phrase{
#Override
public boolean matches(String toMatch){
//Implementation of matches()
}
}
Running the following command: Request.findMatch(allRequests,chat); gives the following error:
Bound mismatch: The generic method findMatch(List<T>, String) of type GSObject<T> is not applicable for the arguments (List<Request>, String). The inferred type Request is not a valid substitute for the bounded parameter <T extends GSObject<T>>
If I do Phrase.findMatch(allPhrases, chat); it does not throw an error, meaning that this has to do with double inheritance. Do I have to write another static function that works with a Class that extends a Class that extends GSObject?
I've looked into making GSObject an interface, but it has some classes that I would like to define (not abstractly) in the class.
Is there something I am missing (in any of the three classes), or do I need to create an interface that defines the function matches() (What I am trying to avoid)?
One option is to make Phrase generic in the same way that GSObject is:
public abstract class Phrase<T extends Phrase> extends GSObject<T> {
public class Request extends Phrase<Request> {
This way, Request extends GSObject<Request> (unlike in your code, where Request extends GSObject<Phrase>).
Another option might be to decouple some of these dependent types by using wildcards, e.g. by one of these:
public static <T extends GSObject<T>> T findMatch(List<? extends T> objects, String toMatch){
public static <U extends GSObject<?>> U findMatch(List<U> objects, String toMatch){
though this can be tricky to get right. Note that with this approach, Request will still advertise that it can handle any List<? extends Phrase>, so you lose some of the benefit of the static type system. (In other words, these versions make your classes more permissive than they're really supposed to be.)
A third option is to do both of the above. It does make sense, after all, for Request.findMatch to take a List<? extends Request>.
Without seeing more of your code, it's hard to know which of these makes most sense for your case.
I am having some problems with my syntax. I am looking all over and could not find the correct thing (I actually do not know, what would be the phrase to search). So here is the problem. For simplicity, lets assume I have 4 classes:
class A:
public abstract class A{
}
class B:
public class B extends A{
//some methods and fields
}
class C:
public class C extends A{
//some other methods
}
class D:
public class D{
protected ? value;
}
Here I have a problem, because I do not know what to put instead of ? in class D, if I want to define ? as some sub-class of A. I know an option is just to write A instead of ?, but I think that this could be more specified, for example something like <T extends A>.
Is this even possible?
-edit-
From answers below, I saw that approach would be, to use raw types. But nevertheless, can anyone confirm that a construct like this, does not exist in java? That you could create a field of generic type T (extending some class), but the class containing this field does not have a generic parameter T?
Use a generic class as follows:
public class D<T extends A> {
protected T value;
}
MyClass isn't dependent of T as you pretend in your comment above. You can instantiate an instance without precising wildcard. Therefore, T would still be remplaced by A at compile-time
This concept is called: Raw types
For more information: http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html
I think you should specific to this value Type at run time .
public class D<T extends A>{
protected T value;
}
D<B> d =new D<B>();
D<A> d1 = new D<A>();
- Use Type Parameter,
Eg:
public class MyClass<T extends A>{
T value;
}