小编典典

有没有办法在 Java 中模拟 C++ 的“朋友”概念?

all

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


阅读 59

收藏
2022-06-07

共1个答案

小编典典

“朋友”概念在 Java 中很有用,例如,将 API 与其实现分开。实现类通常需要访问 API 类内部,但这些不应暴露给 API
客户端。这可以使用下面详述的“朋友访问器”模式来实现:

通过 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);
}

从“朋友”实现包中的类访问示例:

package impl;

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