简体   繁体   中英

Initializing variables in Java as instances of different classes but same initializing keyword

I am new to Java and I finally faced with a problem that I have been postponing for a long time.

I was learning LinkedLists in Java and have the following confusion, please check:

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class LinkedListDemo {
    public static void main(String[] args) {
        List<Integer> myList = new LinkedList<Integer>();

        myList.add(1);
        myList.add(22);
        myList.add(42);

        Iterator it = myList.iterator();

        while(it.hasNext()){
            if((int)(it.next()) == 42)
                System.out.println("We found 42");
        }

        myList.remove();
        System.out.println(myList);
    }
}

Here myList.remove(); gives the following error: "cannot resolve the method 'remove'."

however, if I instantiate myList variable like this

LinkedList<Integer> myList = new LinkedList<Integer>();

I don't have the same error and my code compiles successfully.

I just want to know the working behind this. I mean sometimes I declare ArrayList variables with

List myList = new ArrayList<>();

should I instead declare like this?

ArrayList myList = new ArrayList<>();

thank you

Separate abstraction from implementation

Separate abstraction from implementation allows to code thinking in "I know I'll need here and there a List , but I still don't know/want to choose which kind of List at this moment" or: "I'd like to keep my options open to any List implementation here and there in my code". This is good thing to ease coding.

LinkedList and ArrayList are less abstract than List , which means that these are different implementations of List . Usually you will prefer to use more abstract classes, like List on this case, to separate abstraction from implementation, which is usually a good thing, eg to play with different implementations without changing the rest of your code. So:

List<Integer> myCoolList = new LinkedList<Integer>()

is usually better (as it promotes separation between abstraction and implementation, which is a good habit for your code) than:

LinkedList<Integer> myCoolList = new LinkedList<Integer>()

Now, if you choose to separate abstraction from implementation, of course you will lose the power to use methods specific for each implementation. But usually the most general class (in this case, List ) will give enough alternatives to replace the lost methods ( the LinkedList.remove() method in this case)

Typically your remove method should have parameters.

The List interface doesn't have any remove() method without params.

So when your compiler statically checks your code, cannot find a matching method.

On the other hand, LinkedList has it. So that's why your code works.

Check the java docs for List and the LinkedList .

List

LinkedList

You can check the original code of the link, you can see that it has a remove() method that does not contain any parameters:

 /**
 * Retrieves and removes the head (first element) of this list.
 *
 * @return the head of this list
 * @throws NoSuchElementException if this list is empty
 * @since 1.5
 */
public E remove() {
    return removeFirst();
}

However, this remove() method does not exist in the List class, the parent class of LinkedList, so when you declare in this way:

 List<Integer> myList = new LinkedList<Integer>();

You will not be able to use the remove() method.

But if you use LinkedList initialization, then you will be able to use it, because remove() is unique to the subclass LinkedList.

 LinkedList<Integer> myList = new LinkedList<Integer>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM