Java无法找到addFirst或addLast等方法

时间:2018-05-17 03:16:35

标签: java

import java.util.List;
import java.util.LinkedList;
class Test {
    public static void main(String[] args) {
        List<String> list = new LinkedList<String>();
        list.addLast("string");
        list.removeLast();
    }
}

编译代码时:

$ javac Test.java
Test.java:6: error: cannot find symbol
        list.addLast("string");
            ^
  symbol:   method addLast(String)
  location: variable list of type List<String>
Test.java:7: error: cannot find symbol
        list.removeLast();
            ^
  symbol:   method removeLast()
  location: variable list of type List<String>
2 errors

如果我在双方都使用LinkedList实例化一个LinkedList,那么就不会有错误。我已经知道将List放在左侧更好。为什么会这样?

更新#1 如果变量list的类型为List,为什么以下代码会打印true

class Test {
    public static void main(String[] args) {
       List<String> list = new LinkedList<String>();
       System.out.println(list instanceof LinkedList);
    }
}

我从上述代码的结果中解释的是listLinkedList的实例。如果它是LinkedList的实例,为什么不能调用LinkedList中声明和定义的方法?

更新#2 forEach中有ArrayList方法,但List中没有forEach方法。为什么我在

之后仍然可以在list变量上调用List<String> list = new ArrayList<String>(); 方法
my $s = 'The+quick+brown+fox+jumps+over+the+lazy+dog+that+is+my+dog';
$s = do {local $_ = $s; s/\+/ /g; s/dog/cat/g; $_};

这与lambda表达式有关吗?

4 个答案:

答案 0 :(得分:3)

  

为什么会这样?

Java是一种静态类型语言。这意味着编译器会查看变量的声明类型(不是可能在其中的对象)来确定方法是否存在。

声明的类型List没有这些方法。它们已添加到LinkedList中(来自Deque接口,用于“支持两端插入和删除元素的线性集合”)

  

我已经知道将List放在左侧更好。

是的,这称为“编码到界面”。它避免了您编写仅适用于该接口的特定实现的代码,并且可以在不更新调用代码的情况下更改实现。

但它只有在界面提供您需要的所有内容时才有效。

在您的情况下,您希望使用addLast,它不是常规List界面的一部分。因此,您必须使用Deque(或直接LinkedList)提供的界面。

  

forEach中有ArrayList方法,但List中没有方法。

forEachIterable定义,https://webpack.js.org/concepts/mode/是所有这些东西的超级接口。因此,它也可以在List中使用。

  

如果它是LinkedList的实例,为什么不能调用LinkedList中声明和定义的方法?

再次:静态打字。变量中的实际运行时实例很可能是一个比声明变量更具体的类型。但编译时编译器只能进行静态分析,即查看源代码和声明的方法,字段和变量类型而不是在程序执行期间发生的任何事情。

答案 1 :(得分:1)

Java List接口未定义addLast或removeLast方法。由于您将变量声明为List而不是LinkedList,因此您只能访问List接口上定义的成员。请参阅List documentationLinkedList documentation

答案 2 :(得分:0)

嗯,只是因为java.util.List中没有“addLast()”方法,编译器只知道变量列表是java.util.List的一个实例,它会尝试查找方法在List中命名为addLast()但什么都没有,所以它惊慌失措。
您似乎可能需要了解有关Java的继承和多态系统的更多信息。

答案 3 :(得分:0)

您提供的声明类型是List,分配的类型是LinkedList。虽然该对象是LinkedList,但它只支持声明类型中存在的方法,在您的情况下它支持的列表,它没有特定于{{的方法。 1}}只。列表是LinkedList,也由Interface实现。现在,如果我们将这些方法保留在接口中,那么每个实现类也会实现这些方法,因此没有单一责任和关注点分离的意义。