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.