Java enum with generic attributes - java

I have been trying to create enum that contains generic attribute, for example:
public enum SomeEnum {
SOME_VALUE_1(SomeValue1.class),
SOME_VALUE_2(SomeValue2.class);
private final Class<T extends SomeValue> className;
}
SomeValue1 and SomeValue2 classes implement SomeValue interface. For some reason <T extends SomeValue> is marked with "Unexpected bound" error. If I replace T with ?, there is no error. But it is still puzzling me why it is happening when I use T.
Any help would be highly appreciated.

When you use T extends SomeValue in this way, you are referencing a type variable T that isn't defined, and you aren't allowed to define a type variable there. Only on type variable declarations are you allowed to define a bound such as T extends SomeValue.
On an interface or class, you could define T with the bound you want, but not on an enum. Enums are not allowed to be generic in Java.
You are probably getting the same error on the constructor you haven't shown that accepts a Class<T extends SomeValue> to assign to className. The same reason applies here too.
Using ? extends SomeValue is an upper-bounded wildcard. It basically means "a specific yet unknown type that is SomeValue or a subtype". This is appropriate here, because all you care about here is that the Class is for SomeValue or some implementation class.

<? extends SomeClass> and <T extends SomeClass> are two very different syntaxes.
The first is a wildcard bound, part of a type argument:
TypeArguments:
< TypeArgumentList >
TypeArgumentList:
TypeArgument {, TypeArgument}
TypeArgument:
ReferenceType
Wildcard
Wildcard:
{Annotation} ? [WildcardBounds]
WildcardBounds:
extends ReferenceType
super ReferenceType
The second is a type bound, part of a type parameter:
TypeParameter:
{TypeParameterModifier} Identifier [TypeBound]
TypeParameterModifier:
Annotation
TypeBound:
extends TypeVariable
extends ClassOrInterfaceType {AdditionalBound}
What's the difference between a type parameter and a type argument? A type parameter, like a method parameter, occurs at e.g. a generic class/method declaration:
class Foo<T extends SomeClass> {} // "T extends SomeClass" is a type parameter
class Bar<T> {} // "T" is a type parameter
This is analogous to method parameters:
void foo(int i) {} // "int i" is a method parameter
A type argument, like a method argument, occurs where you use a generic class/method. For example, in a field declaration:
Foo<? extends SomeClass> foo; // "? extends SomeClass" is a type argument
Bar<String> // "String" is a type argument
This is analogous to method arguments that you pass when you call a method:
foo(1); // "1" is a method argument
So really, using T extends SomeClass where you should use ? extends SomeClass makes no sense. You are not declaring a new type variable here. You are merely constructing a generic type.

Related

Inference variable T has incompatible bounds with specific Class<T> and instance <T> in one method

I'm using library which contains method I want to use. Simplified signature would look like this:
final class ThirdPartyClass
{
public static <T> void thirdPartyMethod(Class<T> clazz, T instance)
{
// does something
}
}
Inside thirdPartyMethod() it expects class of T as first argument and an instance of that specific class T as second argument.
Now I have this simple abstract class, which is calling that method:
abstract class Parent<T extends Number>
{
public Parent(T instance)
{
ThirdPartyClass.thirdPartyMethod(instance.getClass(), instance);
}
}
I'm getting an error:
method thirdPartyMethod in class ThirdPartyClass cannot be applied to given types;
required: java.lang.Class, T
found: java.lang.Class<capture#1 of ? extends java.lang.Number>, T
reason: inference variable T has incompatible bounds
equality constraints: capture#2 of ? extends java.lang.Number
lower bounds: T
How can I modify the Parent class so it conforms to expected arguments of thirdPartyMethod()?
If possible with explanation.
According to the return type of Object.getClass()
The actual result type is Class<? extends |X|> where |X| is the
erasure of the static type of the expression on which getClass is
called.
Since T extends Number, the resulting type would be Class<? extends Number>, i.e. means an unknown type extending Number. Which doesn't match T extends Number (i.e. a particular type extending Number which would be provided at runtime).
How can I modify the Parent class so it conforms to expected arguments of thirdPartyMethod()?
1. Introduce a second parameter of type Class<T> in your constructor.
abstract class Parent<T extends Number> {
public Parent(T instance, Class<T> tClass) {
ThirdPartyClass.thirdPartyMethod(tClass, instance);
}
}
2. Perform casting (as have been mentioned in the comments):
ThirdPartyClass.thirdPartyMethod((Class<T>) instance.getClass(), instance);
By the way, instead of calling methods from a constructor (especially ones that are not developed and tested by you/your colleagues) you might consider introducing a factory method that would produce your domain object based on the result of a method call.

Return type of get Class method is different from actual returntype

When I created a instance of a class A and tried to access its getClass() method, its return type is different than what is mentioned in java Object class.
A a = new A() ;
Class<? extends A> clazz = a.getClass();
Even when I access the getClass method as mentioned above in Intellij, it says its return type is Class<? extends A> and even the java doc says it returns wildcard extends upper bound. I can totally accept it. Because I can create instance of B and reference to A and access getClass method.
But why does the return type of the getClass method is justClass<?> in the Object class
Edit 1 (After the comment from Andy Turner)
Class A {
List<?> returningNullList() {
return null;
}
}
When I create a instance of A , and tried to access returningNullList () method, it didn't give me return type as List<? extends A>. But when I tried to access getClass method it says return type is Class<? extends A> although the actual hard-coded return type is Class<? > in Object.java file
Is the getClass method is treated specially by compiler?
But why does the return type of the getClass method is justClass<?> in the Object class
Class<?> is the same as Class<? extends Object>, because all classes (except Object) have Object as a superclass. There's no reason to include that bound explicitly.
Read the documentation, i.e. the javadoc of getClass() in class Object:
The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. For example, no cast is required in this code fragment:
Number n = 0;
Class<? extends Number> c = n.getClass();
The bolding is from the javadoc, not added by me.
For class Object itself, it means that the return type is Class<? extends Object>, but since Class<?> is shorthand for Class<? extends Object>, the javadoc simply shows the shorthand.
Quoting the Java Language Specification, section 4.5.1. Type Arguments of Parameterized Types:
The wildcard ? extends Object is equivalent to the unbounded wildcard ?.

What does this Java syntax mean? (` Class<? extends E> clazz`)

I need a custom method to check for a list containing an instance of a class and call this method but I do not understand this syntax "Class clazz" and I do not understand What's the second parameter of this method
public static <E> boolean containsInstanceOfOidInrArraylist(List<E> Arraylist, Class<? extends E> clazz) {
for (E e : Arraylist) {
if (clazz.isInstance(e)) {
return true;
}
}
return false;
}
Ok, so the first parameter of the function is a List<E> named Arraylist (You shouldn't capitalize variables in Java, name it as such arrayList).
The second parameter is a Class<? extends E> named clazz.
Check manub's explaination of Class<?>:
Class is a parameterizable class, hence you can use the syntax
Class<T> where T is a type. By writing Class<?>, you're declaring a
Class object which can be of any type (? is a wildcard). The Class
type is a type that contains meta-information about a class.
So now you know what Class<?> means, but what about Class<? extends E>?
<? extends E> basically means any class which extends E (or E itself).
So Class<? extends E> clazz means you have a varaible named clazz which is E class or a sub class of E.
See this tutorial: https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html
"Upper Bounded Wildcards
You can use an upper bounded wildcard to relax the restrictions on a variable. For example, say you want to write a method that works on List<Integer>, List<Double>, and List<Number>; you can achieve this by using an upper bounded wildcard.
To declare an upper-bounded wildcard, use the wildcard character ('?'), followed by the extends keyword, followed by its upper bound. Note that, in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces)."
The second parameter is a class that is the same as the class of the objects in the list, or extends it. clazz is used as a variable name because class is a reserved keyword and cannot be used.

Class of a generic Java type cannot be assigned to a variable whose Class type is upper bounded by a generic super type

I use Java 8. In my design a have a few simple classes which model value parameters such as FloatParameter or EnumParameter<E>. A have a common generic super class of these classes (GenericParameter<T>) which implements parameter name and its default value. The sub classes implement other attributes specific to them such as range in case of FloatParameter.
Moreover, I want to work with the types of the parameters regardless of their specific type. But I still want to bound the types in the way that they are sub types of GenericParameter<T>. In order to do that, I created a method such as process(Class<? extends GenericParameter<?>> paramType).
Now, the problem is that the EnumParameter.class cannot be assigned to a variable of type Class<? extends GenericParameter<?>> while FloatParameter.class can be.
Further I list the code for the classes to make it more clear and reproducible:
public class GenericParameter<T> {
protected String name;
protected T defaultValue;
}
public class FloatGenericParameter extends GenericParameter<Float> {
...
}
public class TypedGenericParameter<T> extends GenericParameter<T> {
...
}
Class<? extends GenericParameter<?>> fgpc = FloatGenericParameter.class; // ok
Class<? extends GenericParameter<?>> tgpc = TypedGenericParameter.class; // error: incompatible types: Class<TypedGenericParameter> cannot be converted to Class<? extends GenericParameter<?>>
Class<? extends GenericParameter> tgpc2 = TypedGenericParameter.class; // warning: [rawtypes] found raw type: GenericParameter
Finally, when using a non-generic base class, there is no problem:
public class Parameter {
....
}
public class FloatParameter extends Parameter {
...
}
public class TypedParameter<T> extends Parameter {
...
}
Class<? extends Parameter> fpc = FloatParameter.class; // ok
Class<? extends Parameter> tpc = TypedParameter.class; // ok
Please, do you have any suggestions?
I can go with process(Class<?> paramType) as a workaround or do casts, but I wanted to benefit from the static type checking by the compiler.
EDIT:
I would like to use the cast when registering factories that produce GUI components for each parameter type. The code looks like:
addParameterComponentFactory(EnumParameter.class, new ParameterComponentFactory() { ... })
In such case, the compiler would check the added parameter type at compile time. Also the code would be more self-explaining.
EDIT 2:
Currently, I am using the suggested approach to introduce a type parameter for the addParameterComponentFactory method. The signature looks like this:
public static <P extends GenericParameter<?>> addParameterComponentFactory(Class<P> clazz, ParameterComponentFactory pcf)
With this definition I am able to specify TypedParameter.class (EnumParameter.class - also one type param) as well as I obtain the static type checking.
Let's start with the core bits of your API. You have a generic Parameter<T>
type that represents some named parameter with a value of type T. You have
specialized GUI components designed to edit or display specific types of
parameters, and you want to be able to register factories to create these
components.
class Parameter<T> {
String name;
T defaultValue;
}
class ParameterComponent<P extends Parameter> {
void setParameter(final P p) {}
}
interface ParameterComponentFactory<P extends Parameter> {
ParameterComponent<P> newComponent();
}
class FloatParameter extends Parameter<Float> {}
class FloatParameterComponent extends ParameterComponent<FloatParameter> {}
class EnumParameter extends Parameter<Enum> {}
class EnumParameterComponent extends ParameterComponent<EnumParameter> {}
If I understand you correctly, you're running into trouble figuring out how to
declare a method that statically enforces a relationship between some
Parameter type and a factory for GUI components specialized for that type.
For example, you want to be able to write this:
addComponentFactory(EnumParameter.class, EnumParameterComponent::new); // OK
addComponentFactory(FloatParameter.class, FloatParameterComponent::new); // OK
addComponentFactory(FloatParameter.class, EnumParameterComponent::new); // ERROR!
The problem is related to the rules of generic subtyping, and you can work around them by employing a type variable instead of an embedded wildcard. This should give you the type checking you want, without the need for
nasty casting:
static <P extends Parameter> void addComponentFactory(
final Class<P> parameterType,
final ParameterComponentFactory<? extends P> factory) { ... }
Explanation[1]
Explain the difference between introducing a new type P extends Parameter<?> used in Class<P> and stating
directly Class<? extends Parameter<?>>
This is complicated, so bear with me. Let's talk a bit about wildcards, raw
types, and conversions. Consider the following:
// Scenario 1(a)
GenericParameter raw = /* some value */;
GenericParameter<?> wc = raw;
// Scenario 1(b)
Class raw = GenericParameter.class;
Class<?> wc = raw;
// Scenario 2
Class<GenericParameter> classOfRaw = GenericParameter.class;
Class<GenericParameter<?>> classOfWC = classOfRaw;
Scenarios 1(a) and 1(b) both compile for the same reason: because a raw type
G may undergo an unchecked conversion
to any parameterized type of the form G<T_1, ..., T_n>.
Scenario 2 does NOT compile. But why?
In Scenario 2, neither side in the second assignment is a raw type. For the
assignment to be valid,
there must be either an identity conversion or a widening conversion
from the right-hand type to the left-hand type. For widening conversions on
reference types, the left-hand type must be a supertype of the right-hand type.
When these types are generic, the rules of generic subtyping
apply. Specifically, the type arguments on the left-hand side must
contain
the type arguments on the right-hand side.
An assignment from Class<String> to Class<? extends Object> is valid.
Class<String> is a generic subtype of Class<? extends Object> because
? extends Object contains String. In Scenario 2, for the second
assignment to be valid, GenericParameter<?> would have to contain
GenericParameter, but it doesn't. T is not a subtype of T<?>;
T is a supertype of T<?>. Thus, by the generic subtyping rules,
Class<T> is not a subtype of Class<T<?>>, and the assignment is not
valid.
So why does the following work?
public static <P extends GenericParameter<?>> addParameterComponentFactory(
Class<P> clazz,
ParameterComponentFactory pcf)
addParameterComponentFactory(EnumParameter.class, new ParameterComponentFactory() {})
In the call above, type inference on P is driven entirely by the
Class<P> argument. You are passing a Class<EnumParameter>, so P
in this case gets bound to the raw type EnumParameter. For the constraint
P extends GenericParameter<?> to be satisfied, GenericParameter<?>
must be assignable from EnumParameter, and it is assignable via an
unchecked conversion, just like in Scenarios 1(a) and 1(b).
[1] This explanation is blatant plagarism
an amalgamation of other excellent Stack Overflow answers, mostly by
radiodef.

Using Java Generics error

I have the following code:
String test = "[{\"color\":\"red\"}]";
Class<? extends Base> baseObject = Base.class;
Collection<? extends Base> elements = new ArrayList<Base>();
if (test.startsWith("[")) {
elements.addAll(new ObjectMapper().readValue(test, Collection.class));
} else {
elements.add(new ObjectMapper().readValue(test, baseObject));
}
However I get on
elements.addAll(new ObjectMapper().readValue(test, Collection.class));
a compilation warning:
The expression of type Collection needs unchecked conversion to conform to Collection<? extends capture#1-of ? extends Base>
and for elements.add(new ObjectMapper().readValue(test, baseObject));
a compilation error:
The method add(capture#2-of ? extends Base) in the type Collection<capture#2-of ? extends Base> is not applicable for the arguments (capture#3-of ? extends Base)
What is wrong?
Error can be easily explained. Your collection is defined to hold instances of classes that extends Base. ObjectMapper.readValue is defined as following:
public <T> T readValue(JsonParser jp, Class<T> valueType)
This means that it returns instance of class specified as a second argument. If second argument is Collection.class this method returns Collection. Just Collection, not Collection<? extends Base> and not Collection<Base>. So, java compiler cannot be sure that you are going to put collection that contains correct objects into elements defined as Collection<? extends Base>. Moreover java syntax does not allow to supply as a parameter class with generics, i.e. you cannot call readValue(c, Collection<Base>.class).
The second case is more complicated. baseObject is defined as Class<? extends Base>. elements collection is defined as Class<? extends Base> too. So, what's the problem. The problem is in ?. The question mark means "something that extends Base". But these are 2 different "something" in both cases.
The solution can be either change definition of collection to Class<Base> or to use one class or method generic parameter in both cases, e.g.:
public <T extends Base> myMethod() {
Class<T> baseObject = Base.class;
Collection<T> elements = new ArrayList<T>();
elements.add(new ObjectMapper().readValue(test, baseObject));
}
Now both baseObject and elements use the same type T that indeed extends Base.
You can't add things to a collection with a wildcard type (that doesn't have an explicit lower bound using super, according to Brian; that does make some sense, as a subclass can always be cast to one of its superclasses, but I haven't used super-bounded wildcards much before so I'm not too sure of the details).
http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
Specifically:
Since we don't know what the element type of c stands for, we cannot
add objects to it. The add() method takes arguments of type E, the
element type of the collection. When the actual type parameter is ?,
it stands for some unknown type. Any parameter we pass to add would
have to be a subtype of this unknown type. Since we don't know what
type that is, we cannot pass anything in. The sole exception is null,
which is a member of every type.
Type erasure is a... well, you know.

Categories