10.2 接口中的私有方法

问题

用户希望将私有方法添加到接口中,这些方法可以被接口中的其他方法调用。

方案

Java 9 目前支持在接口方法中使用 private 关键字。

讨论

从 Java 8 开始,开发人员可以为接口编写方法实现,并将它们标记为 defaultstatic。接下来,将 private 方法添加到接口是顺理成章的事情。

私有方法使用关键字 private,且必须有一个实现。与类中的私有方法相似,无法重写接口中的私有方法。更重要的是,私有方法只能从同一个源文件中调用。

例 10-8 虽然略显刻意,但仍有一定说服力。

例 10-8 接口中的私有方法

  1. import java.util.function.IntPredicate;
  2. import java.util.stream.IntStream;
  3.  
  4. public interface SumNumbers {
  5. default int addEvens(int... nums) {
  6. return add(n -> n % 2 == 0, nums);
  7. }
  8.  
  9. default int addOdds(int... nums) {
  10. return add(n -> n % 2 != 0, nums);
  11. }
  12.  
  13. private int add(IntPredicate predicate, int... nums) {
  14. return IntStream.of(nums)
  15. .filter(predicate)
  16. .sum();
  17. }
  18. }

➊ 私有方法

由于接口中的默认访问是公共的,addEvensaddOdds 方法都属于 public,它们传入整数的可变参数列表作为参数。两种方法的 default 实现被委托给 add 方法。除整数的可变参数列表外,add 方法还传入 IntPredicate 作为参数。任何客户端都无法访问被声明为私有方法的 add 方法,即便通过实现 SumNumbers 接口的类也是如此。

例 10-9 显示了私有方法在接口中的应用。

例 10-9 测试接口中的私有方法

  1. class PrivateDemo implements SumNumbers {}
  2.  
  3. import org.junit.Test;
  4. import static org.junit.Assert.*;
  5.  
  6. public class SumNumbersTest {
  7. private SumNumbers demo = new PrivateDemo();
  8.  
  9. @Test
  10. public void addEvens() throws Exception {
  11. assertEquals(2 + 4 + 6, demo.addEvens(1, 2, 3, 4, 5, 6));
  12. }
  13.  
  14. @Test
  15. public void addOdds() throws Exception {
  16. assertEquals(1 + 3 + 5, demo.addOdds(1, 2, 3, 4, 5, 6));
  17. }
  18. }

❶ 实现 SumNumbers 接口的类

❷ 调用委托给私有方法的公共方法

由于只能实例化一个类,程序创建了一个实现 SumNumbers 接口的空类。这个名为 PrivateDemo 的类被实例化,其公共接口方法可以被调用。