Implementation of Friend concept in Java [duplicate]

吃可爱长大的小学妹 提交于 2019-11-30 12:18:26

问题


How does one implement the friend concept in Java (like C++)?


回答1:


Java does not have the friend keyword from C++. There is, however, a way to emulate that; a way that actually gives a lot more precise control. Suppose that you have classes A and B. B needs access to some private method or field in 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);
    }
}

The usageExample() shows how this works. The instance of B doesn't have access to the private fields or methods of an instance of A. But by calling the giveKeyTo(), class B can get access. No other class can get access to that method, since it a requires a valid B as an argument. The constructor is private.

The class B can then use any of the methods that are handed to it in the key. This, while clumsier to set up than the C++ friend keyword, is much more fine-grained. The class A can chose exactly which methods to expose to exactly which classes.

Now, in the above case A is granting access to all instances of B and instances of subclasses of B. If the latter is not desired, then the giveKeyTo() method can internally check the exact type of other with getClass(), and throw an exception if it is not precisely B.




回答2:


Suppose A.foo() should only be called by B. This can be arranged by a token that can only be generated by 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");
        // ...
    }
}

Only B can generate a non-null B.ToA token. If both A and B do not leak this token to the 3rd party, nobody else can invoke A.foo()

If A2 wants to friend B too, it needs a different token type. If it's the same token type, since A got a token of the type from B, A can pretend to be B to A2.

The check is done at runtime, not compile time, that is not perfect. Not a big deal though, since any 3rd party can only invoke A.foo() with a null, it can't be an innocent mistake which we want to check at compile time; it's probably malicious so we don't care to warn the caller at compile time.




回答3:


In Java you can put both (or more) classes into the same package. All methods and fields with the protected qualifier can directly be accessed by all classes in that package.




回答4:


I figured out another way to achieve the same. Basically you check the fully qualified name of the invoking class name. If it matches your "friend" function, then you give access, else you return 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);
    }
}


来源:https://stackoverflow.com/questions/14226228/implementation-of-friend-concept-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!