在Java中实现朋友概念

如何在Java中实现朋友概念(如C ++)?

Java没有C ++中的friend关键字。 然而,有一种方法可以效仿; 这种方式实际上可以提供更精确的控制。 假设您有A类和B类.B需要访问A中的某些私有方法或字段。

 public class A { private int privateInt = 31415; public class SomePrivateMethods { public int getSomethingPrivate() { return privateInt; } private SomePrivateMethods() { } // no public constructor } public void giveKeyTo(B other) { other.receiveKey(new SomePrivateMethods()); } } public class B { private A.SomePrivateMethods key; public void receiveKey(A.SomePrivateMethods key) { this.key = key; } public void usageExample() { A anA = new A(); // int foo = anA.privateInt; // doesn't work, not accessible anA.giveKeyTo(this); int fii = key.getSomethingPrivate(); System.out.println(fii); } } 

usageExample()显示了它的工作原理。 B的实例无法访问A实例的私有字段或方法。但是通过调用giveKeyTo(),B类可以获得访问权限。 没有其他类可以访问该方法,因为它需要有效的B作为参数。 构造函数是私有的。

然后,B类可以使用在密钥中传递给它的任何方法。 虽然设置比C ++好友关键字更笨拙,但它更精细。 A类可以准确选择哪些方法可以准确地公开哪些类。

现在,在上面的例子中,A授予对B的所有实例和B的子类实例的访问权。如果后者不合适,那么giveKeyTo()方法可以在内部用getClass()检查其他实际的类型,并抛出如果它不是精确的B则是一个例外。

假设A.foo()只应由B调用。 这可以通过只能由B生成的令牌来安排。

 public class B { public static class ToA { private ToA(){} } private static final ToA b2a = new ToA(); void test() { new A().foo(b2a); } } public class A { public void foo(B.ToA b2a) { if(b2a==null) throw new Error("you ain't B"); // ... } } 

只有B才能生成非空的B.ToA令牌。 如果AB都没有将此令牌泄露给第三方,则没有其他人可以调用A.foo()

如果A2想要朋友B ,则需要不同的令牌类型。 如果它是相同的令牌类型,因为AB获得类型的标记, A可以假装为BA2

检查是在运行时完成的,而不是编译时间,这并不完美。 虽然没什么大不了的,因为任何第三方只能用null调用A.foo() ,它不能是我们想要在编译时检查的无辜错误; 它可能是恶意的,所以我们不关心在编译时警告调用者。

在Java中,您可以将两个(或更多)类放在同一个包中。 具有protected限定符的所有方法和字段都可以由该包中的所有类直接访问。

我想出了另一种实现相同目的的方法。 基本上,您检查调用类名的完全限定名称。 如果它与您的“朋友”function匹配,则您提供访问权限,否则返回null。

 public class A { private static int privateInt = 31415; public static int getPrivateInt() { if(Throwable().getStackTrace()[1].getClassName().equals(new String("example.java.testing.B"))) { return privateInt; } else { return null; } } } package example.java.testing; public class B { public void usageExample() { int foo = A.getPrivateInt; // works only for B System.out.println(foo); } }