我正在学习SCJP,在学习的过程中我发现了一项看起来非常简单的练习,但我没有解决它,我不明白答案。该练习(摘自 OCP Java SE 6程序员实践考试,Bert Bates和Kathy Sierra),说明如下:
假设:
import java.util.*;
public class MyPancake implements Pancake {
public static void main(String[] args) {
List<String> x = new ArrayList<String>();
x.add("3");x.add("7");x.add("5");
List<String> y = new MyPancake().doStuff(x);
y.add("1");
System.out.println(x);
}
List<String> doStuff(List<String> z) {
z.add("9");
return z;
}
}
interface Pancake {
List<String> doStuff(List<String> s);
}
What is the most likely result?
A. [3, 7, 5]
B. [3, 7, 5, 9]
C. [3, 7, 5, 9, 1]
D. Compilation fails.
E. An exception is thrown at runtime
答案是:
D is correct. MyPancake.doStuff() must be marked public. If it is, then C would be
correct.
A, B, C, and E are incorrect based on the above.
我的猜测是C,因为doStuff方法在MyPancake类中,所以main方法应该可以访问它。
重新考虑这个问题,当从静态上下文调用new时,如果doStuff是私有的,它可能无法访问私有方法。这是真的?我不确定这一点。
但无论如何,我仍然认为它可以访问package-private doStuff方法。 我想我错了,但我不知道为什么。
你能帮帮我吗?
谢谢!
答案 0 :(得分:4)
很遗憾它没有给你一个关于为什么它将无法编译的答案 - 但幸运的是,当你有一个编译器时,你可以找到自己:
Test.java:11: error: doStuff(List<String>) in MyPancake cannot implement doStuff
(List<String>) in Pancake
List<String> doStuff(List<String> z) {
^
attempting to assign weaker access privileges; was public
2 errors
基本上,接口成员始终是公共的,因此您必须使用公共方法实现接口。这不是调用方法的问题 - 这是实现接口的问题。如果您取下“工具”部分,它将正常工作。
来自section 9.1.5 of the Java Language Specification:
所有界面成员都是隐式公开的。根据§6.6的规则,如果接口也被声明为public或protected,则可以在声明接口的包外部访问它们。
答案 1 :(得分:2)
实施Pancake界面时。
您正在MyPancake类中提供doStuff()方法的实现
当您在MyPancake类中提供方法doStuff()的实现时,您还应该将其定义为public,因为接口中的所有成员变量和方法都是默认公用的。
因此,当您不提供访问修饰符时,会降低可见性。
答案 2 :(得分:2)
定义方法时
List<String> doStuff(List<String> s);
在Pancake界面中,你真正说的是:
public List<String> doStuff(List<String> s);
由于界面中的所有方法都是公共的,即使您没有明确表示它们也是如此。
现在,类MyPancake具有分配给doStuff(List s)方法的默认访问权限,因此不遵循接口,代码也无法编译。