0

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
Swadhikar
  • 2,152
  • 1
  • 19
  • 32
  • 1
    You named your generic type using names of standard java classes. Your code is similar to `class Students extends LinkedHashMap {` `Students students = ` but within it `String` and `Integer` will not be treated as `java.lang.String` nor `java.lang.Integer` by default anymore. – Pshemo Jul 11 '16 at 11:11
  • Don't extend, try to use composition. – Gaurava Agarwal Jul 11 '16 at 11:35
  • Thank you Gaurava and @Pshemo – Swadhikar Jul 11 '16 at 11:38

5 Answers5

4

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));
    }
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Well. Though other answers were equally providing the solution, this is what the exact answer I was looking for. Thanks much.. ! – Swadhikar Jul 11 '16 at 11:18
  • 1
    May I know why extending the LinkedHashMap is deprecated. Is it less efficient? – Swadhikar Jul 11 '16 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 Jul 11 '16 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 Jul 11 '16 at 11:27
1

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>
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
1

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> 
Eran
  • 387,369
  • 54
  • 702
  • 768
1

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> ....

Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
1
public class Students<T,E> extends LinkedHashMap<T,E> {
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109