为什么私有类中需要公共方法?

19

我正在查看一部分代码,大致如下:

// compare points according to their polar radius
public static final Comparator<Point2D> R_ORDER = new ROrder();
.
.
.
private static class ROrder implements Comparator<Point2D> {
    public int compare(Point2D p, Point2D q) {
        double delta = (p.x*p.x + p.y*p.y) - (q.x*q.x + q.y*q.y);
        if (delta < 0) return -1;
        if (delta > 0) return +1;
        return 0;
    }
}

为什么在私有静态类内部定义公开方法?如果我将ROrder定义为非静态的公共方法,会带来什么问题?
为什么在私有静态类中定义公共方法?如果我将ROrder定义为非静态公共方法,会有什么危害?

2
可能是包私有类中的公共方法的重复问题。 - Vignesh Vino
4个回答

12

ROrder非静态

将其设为non-static,您将需要容器类的实例来创建ROder的实例,这可能与类的设计不符。只有当您真正需要外部类的实例才能获得内部类的实例时,才应使类非静态。

ROrder公共

同样是因为他们想限制在此类上下文之外使用ROrder。他们不希望任何客户端代码或其他代码自由地创建ROrder实例,因为它们没有任何用处。

为什么我们在私有静态类中具有此类公共方法。

在本例中,因为您正在实现 interface Comparator 并将此比较器传递给其他用途,例如排序,并且您希望 Collections 类具有 compare 方法的可见性,因此即使实现接口的类是private,该方法也必须是public

因此,这只是一种增强代码可读性和使用意图的逻辑方式

逻辑使用

该类想要字符串以某种格式呈现。

public class SomeClass{

     private static class StringHelper{
          //will do the task of parsing and validating that string object
     } 
}

在这种情况下,您不希望将StringHelper类保持为public,因为它的使用范围太局限,无法重用。所以你最好强调通过将其保持为private来实现这一点。如果StringHelper实现了某个接口,那么也可以有一些public方法。

更新:

只有当您真正需要外部类的实例才能获取内部类的实例时,才应该保持类非静态。

对此我认为答案可能过于宽泛,但我会尝试简单解释一下。我指的是如果内部类对象共享外部对象的某些状态,其处理取决于该状态,则需要使用外部类对象与内部类对象共享其状态 ,但如果内部类实例独立于外部类的状态,则将内部类保持为static是安全的。


非常感谢您查看并回答我提出的两个问题,并解释整个过程!关于公共方法compare(),我现在明白了实现接口的方法实现必须是公共的。但如果它是其他方法,将其设置为公共的确实意义不大。对吧? - Somjit
是的,如果它们公开了,那么它们就不再有用了。最好将它们保持为私有状态。 - Narendra Pathai
关于这部分:“只有在您真正需要外部类的实例来获取内部类的实例时,才应将类保持为非静态。”如果您能详细说明一下,我将不胜感激。 - Somjit

6
这个类实现了Comparator接口,因此必须实现其方法。这些实现方法不能是static的。另外,由于接口方法隐式地是public的,无论包含类的可见性如何,它们都必须被声明为public。如果不这样做,编译将失败。这肯定是在这里声明public的原因--它不能不这样做。
无论包含类是static还是public,这都是正确的。在这里,它可以是任何一个,方法内部仍然必须是public和非static的。
其他没有实现接口的方法可以是private的,在一个private类中逻辑上可能应该是这样的,因为否则声明它就没有意义--但Java语法允许这样做。

当你说没有必要声明它,那么这意味着即使我有一个公共方法(除了实现接口的方法之外),由于它在私有类中,那个公共方法也会变成私有的,对吗? - Somjit
从Java / bytecode的角度来看,它在技术上仍然是“public”,但这没有额外的含义。唯一引用它的方法是通过类,如果它是“private”,则在其他地方不可见。 - Sean Owen
我理解了“公共内部私有”部分,请问为什么ROrder在这里是静态的?我在某处读到,当所讨论的方法不会改变任何人的状态时,应该使用静态方法。我认为我有点理解了,但还是希望能得到一些澄清/解释... - Somjit
1
这个问题可能已经在其他SO的问题中得到很好的回答了。它是static,因为ROrder类的实例与包含它的类的实例没有逻辑联系。它是独立的,并且不对包含类的实例进行操作。你可以说static其实是正确的默认值,只有在必要时才会使用非static - Sean Owen

5
所有私有成员(字段、类等)仅在类内部可见。因此,无论您给私有类的方法什么样的可见性 - 所有方法都只能在包含类中可见,因为类本身是私有的。
如果内部类实现了接口或扩展了一个类,则重写的方法不能比超类型中的声明具有更少的可见性,因此这是在私有内部类中拥有公共方法的原因之一。
然而,虽然语法允许私有类具有公共方法,但它不会增加这些方法的可见性,使其足以在包含类外部可见。在Java中有几个例子,修饰符是合法的但没有效果,例如内部接口是隐式静态的(无论是否使用static关键字)。

总体概述非常有帮助,这样我就更容易记住了。但是当你说“..所以这是拥有公共方法的一个原因..”,还有其他原因吗? - Somjit
我一时想不出来。 - Bohemian

1
这个类是私有的,因为开发者不想让ROrder在其他地方实例化。但可以通过常量R_ORDER从其他类中访问它的实例。

这个方法是公共的,有两个原因:首先,compare被定义在Comparator接口中;其次,由于R_ORDER可以从其他类中访问,能够调用该对象上的方法会更方便。在这种情况下,就是compare方法。

最后,如果这个类不是静态的,它将保留对父类的引用,这几乎总是不需要的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接