Reputation: 6799
I have the following two classes
Animal Class
class Animal {
Map<String, A> data = new HashMap <String, A>();
public void setValue(HashMap<String, ?> val)
{
this.data = val;
}
public Map getValue()
{
return this.data;
}
}
Dog Class
class Dog extends Animal {
public void index()
{
Map<String, A> map = new HashMap<String, A>();
map.put("name", "Tommy");
map.put("favfood", "milk"); // want to pass Lists, Integers also
setValue(map);
}
}
As you can see from the above code I am trying to set some values with keys in index
method, but I am getting error warnings from eclipse in both two files. Error Messages are:
In Dog Class File:
Multiple markers at this line
- A cannot be resolved
to a type
- A cannot be resolved
to a type
In Animal Class File :
Multiple markers at this line
- A cannot be resolved to a type
- A cannot be resolved to a type
- Incorrect number of arguments for type Map<K,V>; it cannot be parameterized with arguments
<HashMap<String,A>>
The data type of the keys in HashMap will always be a String but the data types of values would be random, hence I am trying to use Generics.
Coming from PHP background I still haven't been able to grasp the concept of Java Generics. Could you please tell me where is the mistake in my code?
Upvotes: 0
Views: 28697
Reputation: 184
Keep in mind that you shouldn't use the mix of Generic type and RAW type same . a easiest way as my opinion is use Object
instead A
:
Map<String, Object> data = new HashMap <String, Object>();
Upvotes: 0
Reputation: 167
While this kind of setup is not the ideal way to go, one solution is to make your Map a <String, Object>
generic type. In this way you can put whatever you want into the Object part. This will, however, be a pain to pull that information back out. This is how I see your classes changing.
class Animal {
Map<String, Object> data = new HashMap <String, Object>();
public void setValue(Map<String, Object> map)
{
this.data = map;
}
public Map<String, Object> getValue()
{
return this.data;
}
}
class Dog extends Animal {
public void index()
{
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "Tommy");
map.put("favfood", "milk"); // want to pass Lists, Integers also
setValue(map);
}
}
Upvotes: 2
Reputation: 1723
The problem is that you can't just introduce a type parameter in Java generics and expect it to work. For example looking at the Animal
class:
class Animal {
Map<String, A> data = new HashMap <String, A>();
public void setValue(HashMap<String, ?> val)
{
this.data = val;
}
public Map getValue()
{
return this.data;
}
}
Type parameter A
is not defined, so in this case, the compiler will look for a class name A
. You can solve that by introducing a type parameter for the class:
class Animal<A> { // <--- <A> introduces A as a type parameter
Map<String, A> data = new HashMap <String, A>();
public void setValue(HashMap<String, ?> val)
{
this.data = val;
}
public Map getValue()
{
return this.data;
}
}
However the problem with this is, that you then need to define A
when you initialise a new Animal
for example:
Animal<String> dog = new Animal<>();
dog.setValue("name", "max"); //<---- ok
dog.setValue("age", 13); //<---- won't compile
What this means however, is that your data
Map can only map from String
to String
, you will not be able to store integers.
You could get around this by using wildcards, like this for example:
class Animal {
Map<String, ?> data = new HashMap <String, A>();
public void setValue(HashMap<String, ?> val)
{
this.data = val;
}
public Map getValue()
{
return this.data;
}
}
Now you can store every data type derived from Object
in your map, a String
or even an Integer
.
Animal dog = new Animal();
dog.setValue("name", "max"); //<---- ok
dog.setValue("age", 13); //<---- ok
The problem with this solution is that you are only to retrieve the elements in this map in a type save manner.
dog.getValue().get("name") //<---- ok
Object name = dog.getValue().get("name") //<---- ok
-- but --
String name = dog.getValue().get("name") //<---- won't compile
As by this stage, the type information has been lost and you are left with a map that maps String
to Object
Upvotes: 0
Reputation: 93
Your Map<String, A>
has the undefined type A
in its declaration.
The problem is, that A
is never specified and therefore can not be used as a Type for anyting.
The solution would be to either use the wildcard type or use Object
instead of A
.
Here are the two example solutions:
Map<String, ?> data = new HashMap <String, ?>();
or
Map<String, Object> data = new HashMap <String, Object>();
The same thing has to be applied to the map in your Dog
class.
Upvotes: 0
Reputation: 198221
You should not be using a Map
for this; this is not like PHP.
Instead you should be creating a class that knows the type of each of its fields:
class Animal {
String name;
String favfood;
int someIntegerField;
List<Foo> someListField;
...
}
You should really only be using a Map
when all the keys and all the values have the same type.
Upvotes: 1
Reputation: 23049
A cannot be resolved to a type
It just means that you are using class "A" which does not exist. For example here Map<String, A> data
you are saying, that you are creating Map, where string is key and the value is type "A".
In comparision, this Map<String, Integer>
would mean, that you create map, which has string as key and integer as associated value to its key.
Upvotes: 0