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

2022-08-31 05:47:41

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


答案 1

这是我在JAVA中使用的一个小技巧,用于复制C++朋友机制。

假设我有一个类和另一个类。出于仇恨的原因,他们处于不同的包装(家庭)中。RomeoJuliet

Romeo想,只想让她。cuddleJulietJulietRomeocuddle

在C++,会声明为(情人),但在java中没有这样的东西。JulietRomeofriend

以下是类和技巧:

女士优先 :

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

}

所以方法是,但你需要一个来调用它。它将其用作“签名安全性”,以确保只能调用此方法并检查爱是真实的,以便运行时将抛出一个如果它是.Juliet.cuddlepublicRomeo.LoveRomeo.LoveRomeoNullPointerExceptionnull

现在男孩 :

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

该类是公共的,但其构造函数是 。因此,任何人都可以看到它,但只能构建它。我使用静态引用,因此从未使用过的引用只构造一次,并且不会影响优化。Romeo.LoveprivateRomeoRomeo.Love

因此,可以而且只有他可以,因为只有他可以构造和访问一个实例,这是她所要求的(否则她会用一个打你)。RomeocuddleJulietRomeo.LoveJulietcuddleNullPointerException


答案 2

Java的设计者明确拒绝了朋友的想法,因为它在C++中工作。你把你的“朋友”放在同一个包装里。私有、受保护和打包的安全性作为语言设计的一部分强制实施。

James Gosling 希望 Java 能够C++,而不会出错。我相信他觉得朋友是一个错误,因为它违反了OOP原则。包提供了一种合理的方法来组织组件,而不必过于纯粹地对待OOP。

NR指出,你可以使用反射来作弊,但即使这样,也只有在你不使用SecurityManager时才有效。如果打开 Java 标准安全性,则无法通过反射进行作弊,除非您编写安全策略来明确允许它。


推荐