I am trying to extend LinkedHashMap
from my Students class. By this I want to bring in all functionalities of a Map like Map.put(value)
, Map.get(key)
. I just create the object inside PSVM and not making static references but still I get the below error. Can someone point me as to what mistake I am committting here? Also is there a better approach to achieve the task? Thanks in advance!
import java.util.LinkedHashMap;
public class Students<Integer,String> extends LinkedHashMap<Integer,String> {
public static void main(String args[]) { // line 5
Students<Integer,String> students = new Students<>(); // line 6
students.put(1, "s1");
students.put(2, "s2");
students.put(3, "s3");
System.out.println(students.get(1));
}
}
Error Message:
>> javac Students.java
Students.java:5: error: non-static type variable String cannot be referenced from a static context
public static void main(String args[]) {
^
Students.java:6: error: non-static type variable Integer cannot be referenced from a static context
Students<Integer,String> students = new Students<>();
^
Students.java:6: error: non-static type variable String cannot be referenced from a static context
Students<Integer,String> students = new Students<>();
^
Students.java:6: error: unexpected type
Students<Integer,String> students = new Students<>();
^
required: class
found: <Integer,String>Students<Integer,String>
where Integer,String are type-variables:
Integer extends Object declared in class Students
String extends Object declared in class Students
4 errors
5 Answers 5
By doing
class Student<Integer, String>
You have defined your own generic types Integer
and String
. These are associated with the instance of the class Student
however you are also attempting to use these new generic types in your main() method which is a static rather than an instance class and this is not allowed. What you intended to use as java.lang.String
The simple solution is
- don't define you own generic types, you don't need to.
- don't extend
LinkedHashMap
but rather use composition as this limits the methods you expose.
e.g.
public class Students {
private final Map<Integer, String> map = new LinkedHashMap();
public void put(int num, String str) { map.put(num, str); }
public String get(int num) { return map.get(num); }
public static void main(String args[]) {
Students students = new Students();
students.put(1, "s1");
students.put(2, "s2");
students.put(3, "s3");
System.out.println(students.get(1));
}
}
-
Well. Though other answers were equally providing the solution, this is what the exact answer I was looking for. Thanks much.. !Swadhikar– Swadhikar07/11/2016 11:18:00Commented Jul 11, 2016 at 11:18
-
1May I know why extending the LinkedHashMap is deprecated. Is it less efficient?Swadhikar– Swadhikar07/11/2016 11:20:57Commented Jul 11, 2016 at 11:20
-
2@SwadhikarC it not about efficiency its about the number of methods you expose and this class would have to maintain in the future. LinkedHashMap has around 60 methods and there is a very good chance you will end up using one of those methods in a manner that either LHM or you didn't intend.Peter Lawrey– Peter Lawrey07/11/2016 11:25:12Commented Jul 11, 2016 at 11:25
-
1@SwadhikarC say you wanted to add a method
clear(student id)
and this would be fine unless you forgot to provide a student id and cleared the entire map. By extending the class you implicitly have to be aware of every method you might call and this is far less if you delegate.Peter Lawrey– Peter Lawrey07/11/2016 11:27:28Commented Jul 11, 2016 at 11:27
Remove the type variables on the class declaration:
public class Students<Integer,String> extends LinkedHashMap<Integer,String>
should be
public class Students extends LinkedHashMap<Integer,String>
You're actually declaring type variables whose names happen to be the same as Java classes, meaning that your type variables take precedence over the class names and hide them; your class definition is currently semantically identical to:
public class Students<I, S> extends LinkedHashMap<I, S>
-
Well that is a neat explanation.. Thanks for sharing..!Swadhikar– Swadhikar07/11/2016 11:19:11Commented Jul 11, 2016 at 11:19
In
public class Students<Integer,String> extends LinkedHashMap<Integer,String>
you are declaring generic type parameters called Integer
and String
, which hide standard Java class names.
If you want your Students
class to support only java.lang.Integer
keys and java.lang.String
values, use :
public class Students extends LinkedHashMap<Integer,String>
but then you would declare and instantiate the class with :
Students students = new Students();
since it will no longer have generic type parameters.
If you want your Students
class to be generic, use more standard names for the type parameters (which don't hide standard Java classes) :
public class Students<K,V> extends LinkedHashMap<K,V>
With the declaration
class Students<Integer,String> ...
you do not refer to the existent classes java.lang.Integer
and java.lang.String
but you declare your own type parameters for a generic Students
class.
As your class already shall be a LinkedHashMap<Integer,String>
simply remove those type parameters:
class Students extends LinkedHashMap<Integer,String> ...
As a side note: It's a good habit to name your own type parameters for generic types with single uppercase letters, which also prevents such confusions. Example: class Students<I, S> ...
.
public class Students<T,E> extends LinkedHashMap<T,E> {
class Students<I,S> extends LinkedHashMap<I,S> {
Students<I,S> students =
but within itString
andInteger
will not be treated asjava.lang.String
norjava.lang.Integer
by default anymore.