Java为什么不允许接口中包含私有成员?


Answers:


85

根据Java语言规范,(访问控制)

“ Java编程语言提供了访问控制机制,以防止包或类的用户依赖于该包或类的实现的不必要细节。”

访问控制就是隐藏实现细节。接口没有要隐藏的实现。


9
由于我们可以将嵌套类放在接口内,因此可以在接口上实现。这样做是非常错误的,但是我们可以。
emory

28
Java 9允许在接口中使用私有方法,添加默认方法后,这是合乎逻辑的,请参考: bugs.openjdk.java.net/browse/JDK-8071453
Hariharan

3
“这样做是非常错误的。”一如既往地取决于上下文。
JacksOnF1re

5
听起来还不错。接口中的私有方法只能由同一接口中的默认方法访问。好处之一是可以帮助在不破坏封装的情况下将默认方法的实现分解为有意义的较小函数。
亨利·范

48

在Java 9中,接口中的私有方法是可能的。

Java 9规范

javac编译器团队高兴地宣布,从9 b54 JDK构建版本开始的接口中,私有方法的编译器支持已可用。


10
@SebiSebi,您意识到Java是一种实时语言的那一刻。
Arashsoft

@ Arashsoft,OP正在要求字段。
Pacerier

19

专用接口方法是JEP-213的一部分,在Java 9中。由于Java 8中的接口可以具有默认方法,因此私有方法允许多个默认方法使用共享的私有方法。


13

从Java 8开始,接口可以具有默认方法,从Java 9开始,接口可以具有私有方法,该私有方法只能由同一接口中的默认方法访问。


很了解Java-9接口功能。
Ravindra babu

9

接口用于描述由实现接口的任何类提供的API。由于接口从其定义起就没有状态,因此无法在其中声明字段成员。


在Java Land中,成员是字段,方法,构造函数或类。
emory

7

没有办法实现这样的接口。 强烈提出的一个问题的答案强烈表明,不可能(不从根本上改变规则)实现与私有方法的接口-这留下了为什么不允许保护和封装私有方法的问题。

class OuterClass
{
     void run ( MyInterface x )
     {
           x . publicMethod ( ) ;  // why not?
           x . protectedMethod ( ) ; // why not?
           x . packagePrivateMethod ( ) ; // why not?
           x . privateMethod ( ) ; // why not?
     }

     interface MyInterface
     {
           public abstract void publicMethod ( ) ; // OK

           protected abstract void protectedMethod ( ) ; // why not?

           abstract void packagePrivateMethod ( ) ; // in interface default is public, but why not package private

           private void privateMethod ( ) ; // impossible to implement
     }

     class MyImpl implements MyInterface
     {
           public void publicMethod ( ) { } // ok

           protected void protectedMethod ( ) { } // no sweat

           void packagePrivateMethod ( ) { } // no sweat

           private void privateMethod ( ) { } // not happening
     }
}

下面的代码应达到预期的效果。即使所有方法都是公共的,但只有公共方法才是有效的公共。受保护的方法得到有效保护。packagePrivateMethod实际上是packagePrivate。privateMethod实际上是私有的。

class WorkAround
{
     void run ( MyPrivateInterface x )
     {
           x . publicMethod ( ) ;  
           x . protectedMethod ( ) ; 
           x . packagePrivateMethod ( ) ; 
           x . privateMethod ( ) ; 
     }

     public interface MyPublicInterface { void publicMethod ( ) ; }

     protected interface MyProtectedInterface extends MyPublicInterface { void protectedMethod ( ) ; }

     interface MyPackagePrivateInterface extends MyProtectedInterface { void packagePrivateMethod ( ) ; }

     private interface MyPrivateInterface extends MyPackagePrivateInterface { void privateMethod ( ) ; }
}

6

根据Java编程语言,的范围private members仅限于class声明它的范围,并且只能通过that的方法进行访问class。但inteface由于没有方法主体,因此无法在内声明私有成员interface


4

Java在Java 9的接口中允许私有方法。在默认的方法在Java中8这可能是多个默认方法想分享一些代码进行了介绍,那么这段代码可以被移动到一个私有方法不能暴露在外部世界。此错误已得到修复,并且从JDK 9 build 54开始,已经恢复了对私有接口方法的编译器支持。

public interface IData{
   default void processData(int data) {
      validate(data);
      // do some work with it
   }
   default void consumeData(int data) {
      validate(data);
      // do some work with it
   }
   private void validate(int data) {
     // validate data
   }
}

3

这是因为它们将毫无用处。

将无法调用私有方法。

私有成员是实现细节。接口是关于类可以担当的公共角色。


我不同意wrt“将无法调用私有方法。” 对于内部类,将有一种方法-stackoverflow.com/a/10169894/348975
emory 2012年

考虑一下Java 8的默认方法。接口I具有带有很多通用代码的默认方法A和B。要重构此方法,您需要方法C仅包含共享代码并由A和B调用。在Java 8中,这将是默认方法,它公开给所有接口实现者。在Java中9个C可以看到只有一内默认的方法的私有方法
伊万·克雷洛夫

2

私有字段不会完全没有用,因为其他字段和内部类可以访问它们。

但是,即使在嵌套类中也无法实现私有方法,这使它们几乎毫无用处。您可以使用反射来阅读它们,但这只是一个边缘情况。


很抱歉在这里挖墓:( docs.oracle.com/javase/7/docs/api/java/io/Serializable.html在这种情况下如何工作?人们不能实现它,然后覆盖readObject和writeObject方法?我确定我会丢失一些东西
PatrickWalker

1

私人成员在界面上没有任何意义。接口是一种使用已定义方法访问类的方法,您无需查看该类的内部内容。

私人成员不同意这一点。


0

声明为私有的类的成员不会被该类的子类继承。只有声明为protected或public的类的成员才能被声明为非包中声明的包的子类继承。

来源

因此,您在接口中没有任何可用于该私有非继承字段的工作方法,那么为什么它应该存在?


0

是的,不能那样做。对于所有评论为什么不应该评论的人:

想象一下,我拥有使用接口I的ClassA。ClassB扩展了Class A,因此也继承了A中的所有接口方法。

现在,假设我想要在A类中使用私有方法,但也希望通过合同为其他类定义该方法(也许是C类,不一定扩展B类或A类)。

也许对于“初始化”方法,我想对所有使用I接口的类。但是显然我不希望初始化方法是公开的...。因为它只能使用一次,或者在类认为必要时使用,而不仅仅是因为您想随意使用它。

唯一的解决方案是一种解决方法,或者简单地通过将init方法强制进入类本身而不使用接口。

我可以肯定地理解原因,但是有时它仍然可以派上用场。显然,Oracle同意他们在JDK 9中允许私有接口方法的观点。

无论如何,我所做的就是放置一个简单的布尔变量,这样在设置一次之后,接口方法(应该是私有的)可以被标记为true(初始化= true)。然后,当再次调用该方法时,它什么也不做。这样,接口方法可以实现为公共方法,但是由于(我的类的)构造函数首先调用该方法,因此将变量设置为true,因此无法再次调用该方法。

否则,如果您只希望类的内部工作使用它,则必须尝试其他解决方法....也许方法本身会在使用它时将其标志设置为on和off。当标志为false时,该方法不执行任何操作(这将是有人从类外部调用它的时候)。但是,当类自己的方法调用它时,它们很快将标志设置为true,然后调用该方法,然后将标志设置为false?

到底有点静音。就目前而言,将私有类简单地放置到类本身中并完全切断接口可能更好。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.