Is there a way to simulate the C++ 'friend' concept in Java? Is there a way to simulate the C++ 'friend' concept in Java? java java

Is there a way to simulate the C++ 'friend' concept in Java?


Here is a small trick that I use in JAVA to replicate C++ friend mechanism.

Lets say I have a class Romeo and another class Juliet. They are in different packages (family) for hatred reasons.

Romeo wants to cuddle Juliet and Juliet wants to only let Romeo cuddle her.

In C++, Juliet would declare Romeo as a (lover) friend but there are no such things in java.

Here are the classes and the trick :

Ladies first :

package capulet;import montague.Romeo;public class Juliet {    public static void cuddle(Romeo.Love love) {        Objects.requireNonNull(love);        System.out.println("O Romeo, Romeo, wherefore art thou Romeo?");    }}

So the method Juliet.cuddle is public but you need a Romeo.Love to call it. It uses this Romeo.Love as a "signature security" to ensure that only Romeo can call this method and checks that the love is real so that the runtime will throw a NullPointerException if it is null.

Now boys :

package montague;import capulet.Juliet;public class Romeo {    public static final class Love { private Love() {} }    private static final Love love = new Love();    public static void cuddleJuliet() {        Juliet.cuddle(love);    }}

The class Romeo.Love is public, but its constructor is private. Therefore anyone can see it, but only Romeo can construct it. I use a static reference so the Romeo.Love that is never used is only constructed once and does not impact optimization.

Therefore, Romeo can cuddle Juliet and only he can because only he can construct and access a Romeo.Love instance, which is required by Juliet to cuddle her (or else she'll slap you with a NullPointerException).


The designers of Java explicitly rejected the idea of friend as it works in C++. You put your "friends" in the same package. Private, protected, and packaged security is enforced as part of the language design.

James Gosling wanted Java to be C++ without the mistakes. I believe he felt that friend was a mistake because it violates OOP principles. Packages provide a reasonable way to organize components without being too purist about OOP.

NR pointed out that you could cheat using reflection, but even that only works if you aren't using the SecurityManager. If you turn on Java standard security, you won't be able to cheat with reflection unless you write security policy to specifically allow it.


The 'friend' concept is useful in Java, for example, to separate an API from its implementation. It is common for implementation classes to need access to API class internals but these should not be exposed to API clients. This can be achieved using the 'Friend Accessor' pattern as detailed below:

The class exposed through the 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();        }    }}

The class providing the 'friend' functionality:

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

Example access from a class in the 'friend' implementation package:

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