Why do you assign an objects to an interface?

2020-02-26 08:42发布

I have heard several times that when instantiating objects you should do:

"Interface" name = new "Class"();

For example for the class linkedlist that implements List:

List<String> name = new LinkedList<String>();

LinkedList implements many interfaces, including queue, deque, etc. What is the difference between the above code and

LinkedList<String> name = new LinkedList<String>();

or

Queue<String> name = new LinkedList<String>();

Why must the type be specified twice as well; it seems redundant but oracledocs don't seem to mention it.

6条回答
女痞
2楼-- · 2020-02-26 09:10

What is the difference between the above code and

LinkedList<String> name = new LinkedList<String>();

or

Queue<String> name = new LinkedList<String>();

There are a few key differences.

The difference between using the List interface and using a LinkedList object is that I'm defining my interaction with the implementing object to adhere to the List interface. Ultimately, I don't care what the implementation is*, so long as it behaves like a List of some kind.

If I use the concrete LinkedList object, then I not only have to care what the type is, but I can use more things than I probably should - since it implements the Queue interface too, I can do queue-like operations on it, which may or may not be appropriate.

Ultimately, your code should be SOLID; here, we adhere to the dependency inversion principle, which allows us to depend on the interface as opposed to the concrete implementation. It allows us to subsitute the LinkedList for an ArrayList should we want to.

*: Of course you should care what the underlying implementation is, for performance reasons. But, you may not care yet.

查看更多
Ridiculous、
3楼-- · 2020-02-26 09:13

LinkedList<String> name = new LinkedList<String>(); is redundant in Java 7. It can be rewritten to LinkedList<String> name = new LinkedList<>();.

The reason you want to write something similar to:

// Java 7 way:
List<String> name = new LinkedList<>();

is to provide you with the freedom of changing your data collection later, if you change your mind. Your code is much more flexible this way. What you should note about this, is that the methods you are able to use are limited to the left-hand side type (List in this case). This means that you may not get all the functionality you want, if you use a type that is higher in the hierarchy (Object being the extreme example).

查看更多
Rolldiameter
4楼-- · 2020-02-26 09:21
LinkedList<String> name = new LinkedList<>();

Will expose the methods that are defined in LinkedList and its superclasses.

Queue<String> name = new LinkedList<>();

Will expose the methods that are defined in Queue and the interfaces it extends.

You should define the object as a class/interface that holds everything (methods, variables, etc) that you need, while also making it as abstract as possible.

This hides implementation details and allows for easier switching between implementation, for example.

Note that you don't have to specify the type in the initialization due to the diamond operator.

查看更多
5楼-- · 2020-02-26 09:24

If you code to interfaces you can easily switch implementations easily. If an ArrayList suits your needs better than a LinkedList then you can change one line only. If you need a particular method that is in the LinkedList class (or any other of the sub types) then it is perfectly valid to have

LinkedList<String> name = new LinkedList<String>()

As for the redundancy if you are referring to the generic type declaration then I would recommend you look at the Guava libraries. These have some nice static import methods to remove this. For example for an ArrayList it would be

List<String> name = newArrayList()

instead of

List<String> name = new ArrayList<String>()

There is a similar method for LinkedList too.

In Java 7 there is also the diamond operators but this is still a bit more verbose than the static import from Guava.

查看更多
神经病院院长
6楼-- · 2020-02-26 09:28

This isn't as simple as it looks. If you use:

List<Foo> name = new LinkedList<Foo>();

if you ever wanted to switch from linked lists to arraylists it would be less maintenance.

About the redundancy, List name = new LinkedList() declares name of type List and invokes the LinkedList constructor. You could have as follows:

List<Foo> name = someRandomObject.someRandomHelperMethod();

This helper method "just happens" to return a list, so there is no redundancy.

With Java 7 the apparently-redundant generic args can be skipped:

List<Foo> someL = new ArrayList<>();

as opposed to

List<Foo> someL = new ArrayList<Foo>();
查看更多
在下西门庆
7楼-- · 2020-02-26 09:32

Firstly, an Interface is a abstract type that is used to specify what a classes must implement. Any class the implements an interface must satisfy its contract by implementing its method and is of that type.Therefore, by implementing the List interface LinkList is a type of list.

By coding to the interface and not to the concrete class your code becomes more loosely coupled. This means that your code is not bound to the LinkList but rather the List interface and can be changed to anything that implements the list interface at anytime. Therefore, if for some reason the LinkList no longer meets you requirements and you need, lets say a ArrayList instead since it also implements the List interface you can just change to :

List<String> name = new ArrayList<String>();

And all your other programming logic would remain the same,since both classes have the same methods because they implement the same interface.

查看更多
登录 后发表回答