1

我正在学习SCJP,在学习的过程中发现了一个一开始看起来很简单的练习,但是我没有解决它,我不明白答案。该练习(取自OCP Java SE 6 Programmer Practice Exams、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 是私有的,它可能无法访问私有方法。这是真的?我不确定。

但无论如何,我仍然认为它可以访问包私有的 doStuff 方法。我想我错了,但我不知道为什么。

你可以帮帮我吗?

谢谢!

4

3 回答 3

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

基本上接口成员总是公共的,所以你必须用公共方法来实现接口。这不是调用方法的问题——而是实现接口的问题。如果你去掉“实现”部分,它会工作得很好。

Java 语言规范的第 9.1.5 节

所有接口成员都是隐式公共的。根据 §6.6 的规则,如果接口也被声明为 public 或 protected,则它们可以在声明接口的包之外访问。

于 2011-11-15T23:52:43.380 回答
2

当你实现 Pancake 接口时。

您在 MyPancake 类中提供方法 doStuff() 的实现

当您在 MyPancake 类中提供方法 doStuff() 的实现时,您还应该将其定义为公共的,因为接口中的所有成员变量和方法默认情况下都是公共的。

因此,当您不提供访问修饰符时,它会降低可见性。

于 2011-11-15T23:54:04.697 回答
2

当你定义方法时

List<String> doStuff(List<String> s);

在 Pancake 界面中,您真正要说的是:

public List<String> doStuff(List<String> s);

由于接口中的所有方法始终是公开的,即使您没有明确标记它们也是如此。

现在,类 MyPancake 具有分配给 doStuff(List s) 方法的默认访问权限,因此不遵循接口并且代码无法编译。

于 2011-11-15T23:54:14.213 回答