1

In most Java code, I see people declare Java objects like this:

Map<String, String> hashMap = new HashMap<>();

instead of:

HashMap<String, String> hashMap = new HashMap<>();

How is it possible (i know it is but why) to create instance of a Map interface when we know that we can't create instance of an interface.Please explain. Thanks in advance.

amon
136k27 gold badges295 silver badges386 bronze badges
asked May 28, 2017 at 7:59
2
  • A related question (but probably not a duplicate): softwareengineering.stackexchange.com/questions/258105/… Commented May 28, 2017 at 8:03
  • 2
    Both lines of code create an instance of HashMap: that's what new HashMap does. The first one assigns that instance to a variable of type Map. Commented May 28, 2017 at 11:34

4 Answers 4

5

It's called polymorphism:
The instance of a class can be treated as instance of that class but also as an instance of every interface the class implements, since it has to implement all the interface's methods. An interface is a contract that says: "The class implementing me offers at least the same operations that I offer."

Every HashMap is a Map, but not every Map is a HashMap.

answered May 28, 2017 at 8:08
1
  • Well you do get polymorphism from this. You can get polymorphism several different ways. This way is called inheritance. The generic collection just makes it a bit weird. Commented May 28, 2017 at 16:45
2

You cannot create an instance of an interface, because an interface is basically an abstract class without the restriction against multiple inheritance.
And an abstract class is missing parts of its implementation, or is explicitly marked as abstract to prohibit instantiation.

What you can do, and in your example did, is instantiating a class derived from (called implementing) said interface, and upcasting it to any base, be it interface, concrete class or abstract class.

Unless the implementer foolishly broke the contract, the Liskov substitution principle applies and it works just like you actually had instantiated the interface.

answered May 28, 2017 at 13:28
2

Java prohibits interfaces being used to create objects, but it does not prohibit them being used to create variables.

Consider what's actually happening in this code:

 Map<String, String> hashMap = new HashMap<>();
  1. A reference variable is declared on the stack with a name 'hashMap' and type Map<String, String>.

  2. A new instance of type HashMap<> is created on the heap

  3. The 'hashMap' variable is assigned a reference handle (i.e. a memory address value) pertaining to the newly-created instance.

Note:

  • a variable is a named area of memory, on the stack.
  • an object is an instance of a class, on the heap.
  • a reference variable is a variable for a reference handle.
  • a reference handle is a number which represents the memory location of an object on the heap.

This is important because there are two "things" being created in memory, a reference variable and an object. A reference variable is more than just a name for an object; indeed a reference variable can keep a handle on any object, provided that object's type is compatible with the variable's type.

For example, all classes in Java are ultimately derived from Object, so a variable whose type is Object can reference any instance of any class.

However, a variable of type Map<String, String> can only reference an instance of a class which implements the Map<String, String> interface.

Ultimately, there is no problem with creating a variable from an interface, since reference variables do not support any behaviour in themselves (other than for garbage collection). A reference variable is a way for a program to keep track of the objects allocated on the heap, and the type of a variable determines the operations that the program can perform on a referenced object.

answered May 28, 2017 at 17:07
1
Map<String, String> hashMap = new HashMap<>();

The above statement does three things:

  1. Create a new instance of HashMap<String, String>.
  2. Create a variable that can hold a reference to a Map<String, String>.
  3. Store the reference of the object created in step 1 in the variable created in step 2.

It's important to note that underlying object is still a HashMap<String, String>. Since HashMap implements the Map interface, it can be refereed to by a variable with the type Map. In the future, if you needed to change the map implementation, all you need to do is change what is done in step 1.

It's important to note that code that comes after this first line will only have access to methods defined in the Map interface.

For example:

interface SomeInterface {
 void foo();
}
class SomeClass implements SomeInterface {
 void foo() {
 // ...
 }
 void bar() {
 // ...
 }
}
// ...
SomeInterface thing = new SomeClass();
thing.foo(); // works
this.bar(); // doesn't compile because bar() is not defined in SomeInterface
answered May 28, 2017 at 13:03

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.