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);
}
}
我从上述代码的结果中解释的是list
是LinkedList
的实例。如果它是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表达式有关吗?
答案 0 :(得分:3)
为什么会这样?
Java是一种静态类型语言。这意味着编译器会查看变量的声明类型(不是可能在其中的对象)来确定方法是否存在。
声明的类型List
没有这些方法。它们已添加到LinkedList
中(来自Deque
接口,用于“支持两端插入和删除元素的线性集合”)
我已经知道将List放在左侧更好。
是的,这称为“编码到界面”。它避免了您编写仅适用于该接口的特定实现的代码,并且可以在不更新调用代码的情况下更改实现。
但它只有在界面提供您需要的所有内容时才有效。
在您的情况下,您希望使用addLast
,它不是常规List
界面的一部分。因此,您必须使用Deque
(或直接LinkedList
)提供的界面。
forEach
中有ArrayList
方法,但List
中没有方法。
forEach
由Iterable
定义,https://webpack.js.org/concepts/mode/是所有这些东西的超级接口。因此,它也可以在List
中使用。
如果它是
LinkedList
的实例,为什么不能调用LinkedList
中声明和定义的方法?
再次:静态打字。变量中的实际运行时实例很可能是一个比声明变量更具体的类型。但编译时的编译器只能进行静态分析,即查看源代码和声明的方法,字段和变量类型而不是在程序执行期间发生的任何事情。
答案 1 :(得分:1)
Java List接口未定义addLast或removeLast方法。由于您将变量声明为List而不是LinkedList,因此您只能访问List接口上定义的成员。请参阅List documentation和LinkedList documentation
答案 2 :(得分:0)
嗯,只是因为java.util.List中没有“addLast()”方法,编译器只知道变量列表是java.util.List的一个实例,它会尝试查找方法在List中命名为addLast()但什么都没有,所以它惊慌失措。
您似乎可能需要了解有关Java的继承和多态系统的更多信息。
答案 3 :(得分:0)
您提供的声明类型是List,分配的类型是LinkedList
。虽然该对象是LinkedList
,但它只支持声明类型中存在的方法,在您的情况下它支持的列表,它没有特定于{{的方法。 1}}只。列表是LinkedList
,也由Interface
实现。现在,如果我们将这些方法保留在接口中,那么每个实现类也会实现这些方法,因此没有单一责任和关注点分离的意义。