我希望能够在一个包中编写一个Java类,它可以访问另一个包中某个类的非公共方法,而不必使其成为另一个类的子类.这可能吗?

推荐答案

例如,"朋友"的概念在Java中很有用,可以将API与其实现分开.实现类需要访问API类内部是很常见的,但这些不应该公开给API客户端.这可以使用‘Friend Accessessor’模式来实现,具体如下:

通过API公开的类:

package api;

public final class Exposed {
    static {
        // Declare classes in the implementation package as 'friends'
        Accessor.setInstance(new AccessorImpl());
    }

    // Only accessible by 'friend' classes.
    Exposed() {

    }

    // Only accessible by 'friend' classes.
    void sayHello() {
        System.out.println("Hello");
    }

    static final class AccessorImpl extends Accessor {
        protected Exposed createExposed() {
            return new Exposed();
        }

        protected void sayHello(Exposed exposed) {
            exposed.sayHello();
        }
    }
}

提供"朋友"功能的类:

package impl;

public abstract class Accessor {

    private static Accessor instance;

    static Accessor getInstance() {
        Accessor a = instance;
        if (a != null) {
            return a;
        }

        return createInstance();
    }

    private static Accessor createInstance() {
        try {
            Class.forName(Exposed.class.getName(), true, 
                Exposed.class.getClassLoader());
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException(e);
        }

        return instance;
    }

    public static void setInstance(Accessor accessor) {
        if (instance != null) {
            throw new IllegalStateException(
                "Accessor instance already set");
        }

        instance = accessor;
    }

    protected abstract Exposed createExposed();

    protected abstract void sayHello(Exposed exposed);
}

"friend"实现包中类的访问示例:

package impl;

public final class FriendlyAccessExample {
    public static void main(String[] args) {
        Accessor accessor = Accessor.getInstance();
        Exposed exposed = accessor.createExposed();
        accessor.sayHello(exposed);
    }
}

Java相关问答推荐

如何在多个设备上同时运行Android Studio的项目?

Saxon 9:如何从Java扩展函数中的net.sf.saxon.expr. XPathContent中获取声明的变量

Mongo DB Bson和Java:在子文档中添加和返回仅存在于父文档中的字段?

使用ExecutorService时在ThreadFactory中触发自定义newThread函数

Java Streams在矩阵遍历中的性能影响

如何调用Firebase Realtime Database中的子图像列表到android studio中的回收器视图?

ApachePOI:不带换行的新行

Kubernetes的Java客户端检索状态.处于终止状态的Pod的阶段';正在运行';

如何打印本系列的第n项y=-(1)-(1+2)+(1+2+3)+(1+2+3+4)-(1+2+3+4+5)...Java中的(1+2+3+4...+n)

在Spring Boot中使用哪个Java类来存储创建时间戳?

测试何时使用Mockito强制转换对象会导致ClassCastException

把一条整型短裤和两条短裤装成一条长的

在Frege中,我如何将一个字符串安全地转换为一个可能的Int?

为什么有两种实现来检索数组类的组件类型?

如何在太阳系模拟器中添加月球?

Oj算法 MatrixR032从字符串、归一化和余弦相似度计算创建

带有可选部分的Java DateTimeForMatter

AWS Java SDK v2.x中没有setObjectAcl方法

如何使用Java对随机生成的字母数字优惠券代码进行过期设置

无泄漏函数的Java DRY