47

public将方法标记为包私有类中是否有区别?

class SomePackagePrivateClass
{
    void foo();          // package private method

    public void bar();   // public method
}

foo和这里的能见度有什么实际区别bar吗?

4

8 回答 8

49

使用继承的示例:

爪哇

package pkg1

class A {
  void foo();
  public void bar() {};
}

B.java

package pkg1

public class B extends A{

}

C.java

package pkg2

public class C {
  public void doSomething() {
   B b = new B();
   b.bar(); //ok
   b.foo(); //won't work, since foo() is not visible outside of package 'pkg1'

   A a = new A(); //won't work since A is not visible outside of package 'pkg1'
   a.bar(); //won't work, since a cannot be created
  }
}
于 2011-03-10T14:15:19.997 回答
22

如果该类不会被另一个更可见的子类*扩展,唯一的区别是意图的清晰性。将所有方法声明为包私有会使未来的读者更难确定哪些方法应该由同一包中的其他类调用。

*这对我来说作为一种设计解决方案没有多大意义,但在技术上仍然是可能的。

于 2011-03-10T13:52:41.177 回答
10

方法必须是公共的另一种情况是当您创建某个公共类或接口的包私有实现时。由于不允许您降低覆盖方法的可见性,因此这些方法必须是公开的。

于 2011-03-10T14:39:10.530 回答
6

除非该类由公共(或受保护的嵌套)类扩展,否则几乎没有什么区别。

作为一致性问题,我会选择public. 方法应该很少是除publicor之外的任何东西private

java.lang.AbstractStringBuilder包私有类中有许多公共方法的示例。例如,在公共类中length()公开AbstractStringBuilder并在公共类中公开StringBuilder(被覆盖StringBuffer以添加同步)。

于 2011-03-10T13:50:40.593 回答
6

嗯......我也有这个疑问(这就是我搜索这个线程的原因)。这可能是个好问题。

但 ...

转念一想,事情真的比我们想象的要简单。

包私有方法,是包私有方法。

好像是废话?但 ...

一个包私有方法,即使它的类被继承,它仍然是一个包私有方法。

现在更有意义了吗?更详细的解释:

一个包私有方法,即使它的类被更可见的子类继承,它仍然是一个包私有方法。

如果子类属于同一个包,那些包私有的方法也会被继承,但它们仍然是包私有的

如果子类属于不同的包(在这里,我们需要父类是公共的,有一些包私有的方法),那些包私有的方法不会被继承(因为它们根本不可见)。

需要注意的一点,这可能是造成这种疑问的原因,公共类中的包私有方法在其包之外也是不可见的。


上面解释了 package-private 方法。public-method 的情况也是如此。

当一个包私有类被公共子类(同一个包,这是必须的)继承时,它的公共方法作为公共方法被继承,因此它们成为公共类中的公共方法。

在 OP 示例中,由于foo()bar()都在包私有类中,它们的可见性目前仅限于包私有,直到添加更多代码(例如继承)。

希望这足够清楚(和简单)。

PS Java访问控制表

于 2013-05-14T18:08:20.880 回答
6

是的。public包私有类中的方法可能很有用(尽管它们很少见)。来自 java 库的说明性示例(取自经典书籍“有效的 java”):

你见过java.util.JumboEnumSet, java.util.RegularEnumSet吗??可能不是,因为它们是私有的,并且在文档中没有提到。

你用过它们吗??可能是。它们由 的静态方法返回java.util.EnumSet.noneOf(...)。虽然你不能自己构造它们,但是当它们从这个方法返回时,你可以使用它们的公共方法。

这样做的好处是你不知道你正在使用哪一个,甚至不知道它们的存在。Java 根据参数决定哪个更有效,并且可能在较新的版本中使用不同的 on。您只能通过它们的通用界面引用它们来访问它们的功能(无论如何这是一个好习惯!!)

于 2016-12-22T11:25:05.390 回答
0

一个很好的用途是当你想将你的类限制在你的包中,但仍然想使用代理生成的东西,比如@Transactional右上方的方法。

@Service
class SomeService {

   @Transactional
   public void someTxStuff() {
     /// very complicated code here
   }
}

如果someTxStuff是包私有的,@Transactional注释不会有任何效果。

于 2021-01-14T02:33:29.110 回答
-1

foo有能见度default package visibility_ bar_public

于 2011-03-10T13:51:48.737 回答