This question already has answers here:
what is the difference between ? and T in class and method signatures?
(4 answers)
Static generic field in Java
(1 answer)
Closed 1 year ago.
I can define it with '?':
private static final Map<Class<? extends SuperClass>, String> map=
new HashMap<Class<? extends SuperClass>, String>() {
private static final long serialVersionUID = 913392463302576279L;
{
put(SubClaas1.class, "sub1");
put(SubClaas2.class, "sub2");
}
};
But define with T, compile error:
private static <T extends SuperClass> Map<Class<T>, String> map = new HashMap<>();
How to define it use 'T' mode.
Java does not support declaring type parameters for individual fields, only for classes or methods.
You either need to move the declaration of T into the surrounding class itself, or keep using Class<? extends SuperClass> and do unchecked casts to whatever the appropriate type is.
Edit: Sorry, I just noticed that the field is static, in which case you can't just move the type parameter to the class. You need to stick to Class<? extends SuperClass>, either directly or by encapsulating the type unsafety in some custom class map.
A generic type is a generic class or interface that is parameterized over types.
It can be used for a class or a method, but not fields.
If you want to define a map with 'T':
a. use a method:
private static <T extends SuperClass> HashMap<T, String> generateMap() {}
b. use a method:
class Foo<T extends SuperClass> {
private HashMap<Class<T>, String> map = new HashMap<Class<T>, String>();
}
You can get a map of a type based on the needs of the method caller, eg:
public static <T extends SuperClass> HashMap<T, String> giveMeMap() {
return new HashMap<T, String>();
}
so then this will complie:
private static HashMap<SuperClass, String> map = giveMeMap();
but this not, because of the type restriction on the method <T extends SuperClass>
private static HashMap<String, String> map2 = giveMeMap();
is this answering your question?
Related
I'd like to map the Label -> Value of a generic enum instance. This is feasible with this code:
public static <T extends Enum<T>> List<Map<String, String>> mapEnumValues(T[] myEnumValues) {
List<Map<String, String>> list = new ArrayList<>();
for (T myEnumValue : myEnumValues) {
Map<String, String> map = new HashMap<>();
map.put("label", myEnumValue.name());
map.put("value", myEnumValue.toString());
list.add(map);
}
return list;
}
But now I want to use another key for the map, which is for instance a method getLabel() implemented by every one of my enums. For example, given:
public interface Labelizable{
public String getLabel();
}
static public enum Options implements Labelizable {
option01("Option 01", 1), option02("Option 02", 2)
... constructor, getLabel(), ....
So I'd like to replace that row of code with:
map.put("label", myEnumValue.getLabel()); // instead of .name()
In order to do that I should declare something on the signature thst forces the parameter to be an enum that implements the getLabel() method. I tried, for example,
public static <T extends Enum<T implements Labelizable>>
and some other syntax like this with no success. Is there any way to achieve this behaviour, or the fact that enums can't inherit prevent such a method?
The syntax is:
public static <T extends Enum<T> & Labelizable>
List<Map<String, String>> mapEnumValues(T[] myEnumValues) {
You put the superclass that your generic parameter has to inherit first, then the interfaces that it has to implement, all separated by &.
I have an interface and class like following:
public interface Message extends Wrappable
{
}
public class MessageImpl implements Message
{
}
I want to use Java generics to store these Classes into a Map with interface as key and impl as value as:
map.put(Message.class, MessageImpl.class);
I want it to be typesafe, where key must extends Wrappable and value must extend key class.
Any help on this?
A basic Map can't do this type safely, but you can create a simple wrapper around a Map to enforce type safety. That might look something like
class MyMap {
private final Map<Class<?>, Class<?>> map = new HashMap<>();
public <A extends Wrappable, B extends A> void put(
Class<A> interfaceClass, Class<B> implClass) {
// you can't statically enforce that A is an interface
// and B is a concrete class, though you can do it at runtime
assert interfaceClass.isInterface();
assert !Modifier.isAbstract(implClass.getModifiers());
map.put(interfaceClass, implClass);
}
public <A extends Wrappable> Class<? extends A> get(Class<A> interfaceClass) {
return (Class<? extends A>) map.get(interfaceClass);
}
}
Could any on tell why am I getting following error when I am trying to add Float in the map which I am trying to use with bounded wild card?
The error I'm getting is:
The method put(String, Class<? extends Number>) in the type Map<String,Class<? extends Number>> is not applicable for the arguments (String, Float)
And here is my code:
public final static Map<String, Class<? extends Number>> SECTION_DATA = new HashMap<String, Class<? extends Number>>();
static
{
SECTION_DATA.put("test", new Float(1));
}
The second argument is of type Class, and Float is not a subclass of Class.
It sounds like you're looking for
public final static Map<String, Number> SECTION_DATA = new HashMap<String, Number>();
This map will accept values of any class that subclasses Number.
You cannot add a Float to a map that has Class values, because although Floatis a class, it is not subclass of Class.
I am trying to write a method that takes in any subclass of MyInterface as a parameter, but getting syntax errors.
public Map<String, List<T extends MyInterface>> makeMap(List<T extends MyInterface>) {
Map<String, List<T extends MyInterface>> myMap = ...
return myMap;
}
This syntax is not valid. The signature gives the error "misplaced construct". But, the idea is that I can pass any subclass of MyInterface inn place of T. Can this be done in Java? how?
You are mixing up the concepts of declaring a generic type and referring to that generic type. Assuming that you want the method to be generic, declare the generic type parameter before the return type, then refer to it plainly as T elsewhere:
// Declaration ref ref
public <T extends MyInterface> Map<String, List<T>> makeMap(List<T>) {
// ref
Map<String, List<T>> myMap = ...
return myMap;
}
public <T extends MyInterface> Map<String, List<T>> makeMap(List<T> myList) {
More on generic methods here
I also noticed that in your original method declaration, you didn't have a variable defined for your method parameter.
Is there a way to define a type for a Collection?
If I have the following:
private Map<String, A> myMap;
then is there a way to define Map<String, A> as a new type MapOfTypeA, for example, so that I can define myMap as
private MapOfTypeA myMap;
as an extension of this, is there a way to have the following:
myMap = new MapOfTypeA();
actually be
myMap = new HashMap<String, A>();
I'm not sure of what to call what I am asking, but I think I have explained it. In C or C++ it would be a typedef, I think.
You could define MapOfTypeA as
class MapOfTypeA extends HashMap<String, A> {
}
But not sure what the purpose is. If your concern is verbosity, then Java 7 has introduced the diamond operator that you can use to declare your map like this:
Map<String, A> myMap = new HashMap<> ();
instead of
Map<String, A> myMap = new HashMap<String, A> ();
Something like this?
class MapOfTypeA extends HashMap<String, A> { }
Which makes the following declaration perfectly valid:
private MapOfTypeA myMap;
That kind of class declaration is all you need to achieve the abbreviated syntax you're looking for. Of course the comments on why you're doing this will be an order of magnitude longer than the definition itself. ;-)
There are no typedefs or aliases in Java. The closest you can get is to create a new type, which is almost the same thing but not quite:
class MapOfA extends <String, A> {}
MapOfA aMap = new MapOfA();
The only place I have found this useful is for (sort of) partial specialization:
class MapFromString<X> extends Map<String, X> {}
I can think of at least two options
1) keep the value object generic, keys are always one type
public class StringKeyedMap<V> extends ConcurrentHashMap<String,V> {
public static void main(String[] args) {
StringKeyedMap<Integer> stringToIntegerMap = new StringKeyedMap<Integer>();
stringToIntegerMap.put("some-key", Integer.valueOf(7));
}
}
2) key and value of the map are always a single type
public class MyMap extends ConcurrentHashMap<String,Integer> {
public static void main(String[] args) {
MyMap myMap = new MyMap();
myMap.put("some-key", Integer.valueOf(7));
}
}
is that what you mean?
public class MapOfTypeA extends HashMap<String, A>{}
Then you could use your MapOfTypeA instances wherever you would need a HasMap.
...but I cannot really see where this would be useful(?)
In Java Terms, it is call Generics: http://en.wikipedia.org/wiki/Generics_in_Java
And the way you defined it is perfectly correct.
but you probably need to revert how you define your hashmap.
If you want the hashmap to have both A and MapOfTypeA, and MapOfTypeA is a subclass of A
class MapOfTypeA extends A, then your hashmap should defined this way.
HashMap<String, MapOfTypeA> myMap;