在Java中,什么时候应该在接口中使用私有示例方法?

h9vpoimq  于 2024-01-05  发布在  Java
关注(0)|答案(3)|浏览(176)

从Java 9开始,接口中的方法可以是私有的。私有方法可以是静态的或示例方法。由于私有方法只能在接口本身的方法中使用,因此它们的用途仅限于作为接口的其他方法的帮助器方法。

Cay S. Horstmann,Core Java Volume I - Fundamentals

我知道我们可以把公共功能放在private方法中,而不是让它对public访问。但是我们可以在这里有两种private方法:
1.第一个月

  1. private static
    使用private static方法是可以理解的,但是我们什么时候应该使用private方法呢?我们这里不处理示例,因为这是一个接口,那么为什么允许创建private方法呢?我们不需要只使用private static方法吗?
3wabscal

3wabscal1#

接口用于定义对象的行为。这意味着接口的所有方法都是公开的。当使用默认方法时,我们可以提供定义方法的标准实现,提供跨类边界的代码重用。
在某些情况下,功能是必需的(也许只是为了在不同的 *default方法 * 中重用代码),但不应该暴露,因为它会污染类/对象的命名空间。这就是 *private default方法 * 派上用场的地方。例如private default方法可以是工厂,验证或默认状态处理。

  1. package com.company;
  2. import java.util.List;
  3. import java.util.function.Predicate;
  4. import java.util.stream.Collectors;
  5. public class Main {
  6. public static void main(final String[] args) {
  7. var messages =
  8. List.of(
  9. MessageQueue.newSubject("Message 1"),
  10. MessageQueue.newTopic("Message 2"),
  11. MessageQueue.newTopic("Message 3"));
  12. final MessageQueueAdapter1 queue1 = () -> messages;
  13. inspectQueue(queue1);
  14. final MessageQueueAdapter2 queue2 = () -> messages;
  15. inspectQueue(queue2);
  16. }
  17. private static void inspectQueue(final MessageQueue queue) {
  18. final List<Message> messagesWithSubject = queue.getMessagesWithSubject();
  19. assert messagesWithSubject.size() == 1 : "expected one message with 'Subject'";
  20. final List<Message> messagesWithTopic = queue.getMessagesWithTopic();
  21. assert messagesWithTopic.size() == 2 : "expected two message with 'Topic'";
  22. assert !queue.getMessages().isEmpty() && 3 == queue.getMessages().size()
  23. : "expected three messages in total";
  24. }
  25. @FunctionalInterface
  26. interface Message {
  27. private static boolean isPrefixedBy(final String message, final String prefix) {
  28. return message != null && !message.isEmpty() && message.startsWith(prefix);
  29. }
  30. default boolean hasSubject() {
  31. return isPrefixedBy(this.getMessage(), MessageQueue.PREFIX_SUBJECT);
  32. }
  33. default boolean hasTopic() {
  34. return isPrefixedBy(this.getMessage(), MessageQueue.PREFIX_TOPIC);
  35. }
  36. String getMessage();
  37. }
  38. interface MessageQueue {
  39. String PREFIX_SUBJECT = "Subject: ";
  40. String PREFIX_TOPIC = "Topic: ";
  41. private static Message newMessage(final String message) {
  42. return () -> message;
  43. }
  44. static Message newSubject(final String message) {
  45. return newMessage(PREFIX_SUBJECT + message);
  46. }
  47. static Message newTopic(final String message) {
  48. return newMessage(PREFIX_TOPIC + message);
  49. }
  50. List<Message> getMessages();
  51. List<Message> getMessagesWithSubject();
  52. List<Message> getMessagesWithTopic();
  53. }
  54. @FunctionalInterface
  55. interface MessageQueueAdapter1 extends MessageQueue {
  56. private static List<Message> filterBy(
  57. final List<Message> messages, final Predicate<Message> predicate) {
  58. return messages.stream().filter(predicate).collect(Collectors.toList());
  59. }
  60. /** {@inheritDoc} */
  61. @Override
  62. default List<Message> getMessagesWithSubject() {
  63. return filterBy(this.getMessages(), Message::hasSubject);
  64. }
  65. /** {@inheritDoc} */
  66. @Override
  67. default List<Message> getMessagesWithTopic() {
  68. return filterBy(this.getMessages(), Message::hasTopic);
  69. }
  70. }
  71. @FunctionalInterface
  72. interface MessageQueueAdapter2 extends MessageQueue {
  73. private List<Message> filterBy(final Predicate<Message> predicate) {
  74. return this.getMessages().stream().filter(predicate).collect(Collectors.toList());
  75. }
  76. /** {@inheritDoc} */
  77. @Override
  78. default List<Message> getMessagesWithSubject() {
  79. return filterBy(Message::hasSubject);
  80. }
  81. /** {@inheritDoc} */
  82. @Override
  83. default List<Message> getMessagesWithTopic() {
  84. return filterBy(Message::hasTopic);
  85. }
  86. }
  87. }

字符串

展开查看全部
sc4hvdpw

sc4hvdpw2#

好了,又一次尝试实际回答OP的问题。当你需要从一个私有方法调用接口上的另一个非静态方法时,私有方法不能是静态的。例如,如果下面的私有方法是静态的,那么就会出现编译错误:

  1. public interface InterfaceWithMethods {
  2. public default void doSomething() {
  3. doSomethingCommon();
  4. }
  5. public default void doSomethingElse() {
  6. doSomethingCommon();
  7. }
  8. public void actuallyDoSomething();
  9. private void doSomethingCommon() {
  10. System.out.println("Do something first.");
  11. actuallyDoSomething();
  12. }
  13. }

字符串

展开查看全部
stszievb

stszievb3#

我在阅读OCP Java 17考试指导书时也遇到了同样的问题,这里是我在阅读时意识到的一些见解。
default & private非静态方法可以调用抽象方法。(接口中存在private非静态方法的原因。它与实现类的示例相关联。)
私有静态方法不能静态引用非静态抽象方法。(注意抽象不能和静态一起使用。)

  1. interface PrivateMethodEx {
  2. void abstractMethod();
  3. default void defaultMethod() {
  4. anotherPrivateMethod();
  5. anotherPrivateStaticMethod();
  6. abstractMethod();
  7. }
  8. private void privateMethod() {};
  9. private static void privateStaticMethod() {};
  10. private void anotherPrivateMethod() {
  11. privateMethod();
  12. privateStaticMethod();
  13. abstractMethod();
  14. }
  15. private static void anotherPrivateStaticMethod() {
  16. // privateMethod(); // Compile error. Cannot make static reference to non-static method.
  17. privateStaticMethod();
  18. // abstractMethod(); // Compile error. Cannot make static reference to non-static method.
  19. }
  20. }

字符串

展开查看全部

相关问题