比类访问修饰符限制更少的成员访问修饰符有啥用?

Posted

技术标签:

【中文标题】比类访问修饰符限制更少的成员访问修饰符有啥用?【英文标题】:Whats the use of less restrictive member access modifiers than the class access modifier?比类访问修饰符限制更少的成员访问修饰符有什么用? 【发布时间】:2020-02-05 14:55:37 【问题描述】:

假设我有一个包含一些成员的类,并且这些成员的访问修饰符比类本身的限制更少。

一个具体的例子可以是:

package apples;

class A  // package private
    public int foo()  // public (=> less restrictive than *package private*)
        return 42;
    

据我了解,class 访问修饰符比 member 访问修饰符更严格,将覆盖限制较少的 member 访问修饰符。因此,限制较少的 member 访问修饰符应该没有任何效果。

我的理解正确吗? 如果不是,会有什么后果? 限制较少的成员访问修饰符有哪些正当理由? 最后,有哪些最佳实践可以遵循?

我也做了一些实验,因为我认为一旦我开始传递函数引用可能会产生后果,但即便如此访问修饰符似乎并不重要。

我构造的情况如下:

apples.B 提供了一个公共方法 bla(),它返回对 apples.A.foo 的引用。 然后pizzas.C 调用apples.B.bla 以获取对A.foo 的引用并调用它。 所以A.foo()C 不直接可见,但只能通过B.bla() 间接访问

我测试过,是否将foo()的访问修饰符设置为包私有没有区别。

package apples;

import java.util.function.IntSupplier;

public class B 
    public IntSupplier getReferenceToAFoo() 
        A aInstance = new A();
        return aInstance::foo;
    

package pizzas;

import apples.B;

import java.util.function.IntSupplier;

public class C 
    private int callAFooIndirectly() 
        B bInstance = new B();
        IntSupplier intsupplier = bInstance.getReferenceToAFoo();
        return intsupplier.getAsInt();
    

    public static void main(String[] args) 
        C cInstance = new C();

        int i = cInstance.callAFooIndirectly();
        System.out.println(i);
        assert 42 == i;
    


【问题讨论】:

到目前为止,这种设计最常见的原因是使用非公共类提供公共 API 方法(例如来自接口或扩展抽象类的方法)的实现。 JDK 本身充满了这样的类(例如:java.util.Collections.SingletonSet<E>private in java.util.Collections)。 【参考方案1】:

我的理解正确吗?

是的。

什么是限制较少的成员访问修饰符的正当理由?

两个原因:

有时,您正在实现一个接口;接口方法必须是public 它可以更轻松地更改班级的整体访问权限。例如,如果您将所有想要公开的方法标记为 public,即使是在包私有类中,那么稍后您所要做的就是将 public 添加到该类中以使该类公开声明。

最后,有哪些最佳实践可以遵循?

这是一个见仁见智的问题,因此不太适合 Stack Overflow 问题或答案。做你和/或你的团队认为合理的事情,和/或做你团队的风格指南告诉你做的事情。

【讨论】:

以上是关于比类访问修饰符限制更少的成员访问修饰符有啥用?的主要内容,如果未能解决你的问题,请参考以下文章

访问说明符和访问修饰符有啥区别?

typescript 访问修饰符和 javascript 访问修饰符有啥区别?在使用打字稿时我应该更喜欢哪一个?

在 C# 中,public、private、protected 和没有访问修饰符有啥区别?

Java基础 ----类成员修饰符

成员变量和成员方法的访问控制修饰符都有哪些?

在Java和c#中如果不写访问修饰符,类和类成员默认的是啥访问修饰符?