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

Viewed 96588

I would like to be able to write a Java class in one package which can access non-public methods of a class in another package without having to make it a subclass of the other class. Is this possible?

18 Answers

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

As far as I know, it is not possible.

Maybe, You could give us some more details about Your design. Questions like these are likely the result of design flaws.

Just consider

  • Why are those classes in different packages, if they are so closely related?
  • Has A to access private members of B or should the operation be moved to class B and triggered by A?
  • Is this really calling or is event-handling better?

Not using a keyword or so.

You could "cheat" using reflection etc., but I wouldn't recommend "cheating".

In Java it is possible to have a "package-related friendness". This can be userful for unit testing. If you do not specify private/public/protected in front of a method, it will be "friend in the package". A class in the same package will be able to access it, but it will be private outside the class.

This rule is not always known, and it is a good approximation of a C++ "friend" keyword. I find it a good replacement.

I think that friend classes in C++ are like inner-class concept in Java. Using inner-classes you can actually define an enclosing class and an enclosed one. Enclosed class has full access to the public and private members of it's enclosing class. see the following link: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

If you want to access protected methods you could create a subclass of the class you want to use that exposes the methods you want to use as public (or internal to the namespace to be safer), and have an instance of that class in your class (use it as a proxy).

As far as private methods are concerned (I think) you are out of luck.

I prefer delegation or composition or factory class (depending upon the issue that results in this problem) to avoid making it a public class.

If it is a "interface/implementation classes in different packages" problem, then I would use a public factory class that would in the same package as the impl package and prevent the exposure of the impl class.

If it is a "I hate to make this class/method public just to provide this functionality for some other class in a different package" problem, then I would use a public delegate class in the same package and expose only that part of the functionality needed by the "outsider" class.

Some of these decisions are driven by the target server classloading architecture (OSGi bundle, WAR/EAR, etc.), deployment and package naming conventions. For example, the above proposed solution, 'Friend Accessor' pattern is clever for normal java applications. I wonder if it gets tricky to implement it in OSGi due to the difference in classloading style.

I once saw a reflection based solution that did "friend checking" at runtime using reflection and checking the call stack to see if the class calling the method was permitted to do so. Being a runtime check, it has the obvious drawback.

As of Java 9, modules can be used to make this a non-issue in many cases.

Related