I want to do something like that:
public final <T>T getObject(Class <T extends MyObject> myObjectClass){
//...
}
IDE complains about syntax error. How to write this correctly?
You declared the generic type bound in the wrong place.
It should be declared within the declaration of the generic type parameter:
public final <T extends MyObject> T getObject(Class<T> myObjectClass)
{
//...
}
Related
I have a class Saver<T> with one generic type argument <T>. In my Saver<T> class, I'm attempting to define the following static map:
public abstract class Saver<T> {
private static final Map<Class<E>, Class<? extends Saver<E>>> DEFAULT_SAVERS = new HashMap<>();
}
Of course, this gives me an error because the compiler doesn't know what E is. How can I create this map? The map should have Classes for keys, and Savers with that class as its generic type as its values. Is this possible? How can I do this?
There's no typesafe way to declare it. You'll have to use wildcards and control how it's accessed to prevent heap pollution:
private static Map<Class<?>, Saver<?>> DEFAULT_SAVERS = new HashMap<>();
public static <T> void put(Class<T> clazz, Saver<T> saver) {
DEFAULT_SAVERS.put(clazz, saver);
}
public static <T> Saver<T> get(Class<T> clazz) {
return (Saver<T>)DEFAULT_SAVERS.get(clazz);
}
Here's a visual of the problem:
As can be seen from the visual, the IDE is showing a compile-time error to which it does not allow the class to be inserted into the Map.
Here's a simplified version:
#Override
public <T extends Comparable> void transactPersistentEntityStore(...) {
Map<Class<T>, ComparableBinding> propertyTypeMap = new HashMap<>();
propertyTypeMap.put(EmbeddedArrayIterable.class, EmbeddedEntityBinding.BINDING);
propertyTypeMap.put(EmbeddedEntityIterable.class, EmbeddedEntityBinding.BINDING);
// ...
}
Even if both EmbeddedArrayIterable and EmbeddedEntityIterable implements Comparable
Am I missing or misunderstanding something on generics?
You can simplify the point of the problem to this code snippet:
public <T extends Comparable> void m1(T x) {
Class<? extends Comparable> x1Class = x.getClass();
Class<T extends Comparable> x2Class = x.getClass();
}
Or even to this:
public <T> void m2(T x) {
Class<?> x1Class = x.getClass();
Class<T> x2Class = x.getClass();
}
The line with the variable x2Class has an error in these methods.
This is because the compiler throws away the Generics and thus there is no type T at runtime. T is not reifiable. You cannot obtain the type T at runtime.
Have also a look at this article: Why following types are reifiable& non-reifiable in java?
Can someone help me with an explanation as to why this is a type mismatch?
public interface ResponseContainer<T extends ResponsePayload<T>> {
public T getResponsePayload();
}
public interface ResponsePayload<T> {
public T getPayload();
}
protected abstract <T> Class<? extends ResponseContainer<? extends ResponsePayload<T>>> getResponseClazz(Class<? extends ResponsePayload<T>> responseClazz);
And to call it:
private void tryThis() {
ResponseContainer<AccountsResponse> contaner = getResponseClazz(AccountsResponse.class);
}
Gives the compilation error:
Type mismatch: cannot convert from Class<capture#22-of ? extends ResponseContainer<? extends ResponsePayload<AccountsResponse>>> to ResponseContainer<AccountsResponse>
Is this because I can't syntactically use ? extends T when something is implementing it rather than extending it?
You need to change the return type of getResponseClazz. You also should change your generic definition to avoid wildcards. The signature should be
protected abstract <T extends ResponsePayload<T>> ResponseContainer<T> getResponseContainer(Class<T> responseClazz);
EDIT Thanks to Thilo, method name changed
I have this code:
public interface IDimension<S extends IDimension<S,T>, T extends Number> extends Comparable<S> {
T toNumber();
default T toBaseNumber() {
return toNumber();
}
S fromNumber( T units );
Class<T> numberType();
}
When I implement IDimension like below(Implementation1), I get 'Type parameter 'TestBaseSample' is not within its bound; should implement 'IDimension<TestBaseSample<Float,Integer>, java.lang.Long>' error:
Implementation1 :
class TestBaseSample<Integer, Float>
implements IDimension<TestBaseSample<Float, Integer>, Long> {
}
I understand why 'Implementation1' gives error, but not able to understand why 'Implementation2' and 'Implementation3' works?
Implementation2:
class TestBaseSample2<Integer, Float>
implements IDimension<TestBaseSample2<Float, Float>, Long> {
}
Implementation3 :
class TestBaseSample3<Integer, Float>
implements IDimension<TestBaseSample3<Integer, Integer>, Long> {
}
It looks like you are attempting to create a concrete type, but you are actually creating generic parameters and giving them the names of java classes.
Consider your first example TestBaseSample2 if we change the generic parameters to T and S
class TestBaseSample2<T, S>
implements IDimension<TestBaseSample2<S, S>, Long> {
}
Now, you should be able to make an instance provided S is a Long and T can be anything else.
Here is a simpler example.
static class OtherList<Integer> extends ArrayList<Integer>{}
public static void main (String[] args) throws java.lang.Exception
{
OtherList<String> list = new OtherList<>();
list.add("this");
System.out.println(list.size());
}
Remove all types from your implementations (and never name generic parameters using class names, especially classes from the JDK - use single letters):
class TestBaseSample implements IDimension<TestBaseSample, Long> {
}
class TestBaseSample2 implements IDimension<TestBaseSample2, Long> {
}
class TestBaseSample3 implements IDimension<TestBaseSample3, Long> {
}
Here is my problem:
my function in class A:
public void setData(Map<String,? extends ArrayList<? extends SomeInterface>>){...}
my call:
Map<String, ArrayList<ImplementsSomeInterface>> a=...;
instanceOfA.setData(a); //does not compile
instanceOfA.setData((Map<String,? extends ArrayList<? extends SomeInterface>>) a); // works thanks to the Casting.
I don't think this is clean. Is there a way to avoid the casting without droping the wildcard use in the function?
First your setData method should read:
public void setData(Map<String,? extends List<? extends SomeInterface>>)
Your map declaration should read:
Map<String, List<ImplementsSomeInterface>> a = ...;
Which is pretty much what you've got following your edits to the original question. The change I've made from ArrayList to List doesn't effect the behaviour of the code.
Following comments:
public static void main()
{
Map<String, List<Double>> map = new HashMap<String, List<Double>>();
map.put("prices", new ArrayList<Double>(Arrays.asList(1.1, 2.2, 3.3)));
setData(map);
}
public static void setData(Map<String,? extends List<? extends Serializable>> map)
{
}
The problem is that setData takes as an argument a
Map<String,? extends ArrayList<? extends SomeClass>>Map>
whereas in your first call(the one that doesn't compile) you are trying to pass it a Map<String,? extends SomeClass>
Java cannot automatically cast a subclass of
SomeClass
to a subclass of
ArrayList<? extends SomeClass>
because it is not neccesarily an instance of ArrayList.