4

I was trying to test working of private interfaces and wrote the code below. I can understand that a situation might arise to declare private interfaces if we don't want any other class to implement them but what about variables? Interface variables are implicitly public static final and hence i was able to access them even if interface was declared private. This can be seen in code below.

 public class PrivateInterfaceTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        TestingInterfaceClass test = new TestingInterfaceClass();
        TestingInterfaceClass.inner innerTest = test.new inner();

        System.out.println(innerTest.i);

    }

}

class TestingInterfaceClass {

    private interface InnerInterface {
        int i = 0;
    }

    class inner implements InnerInterface {

    }
}

Does it mean that we can never really have private interface in true sense? And does it really make sense to if have private interface if we can access variables outside private interface?

EDIT: Just want to add that same situation will not arise if we have private inner class. A private variable in inner class will never get exposed.

Lokesh
  • 7,810
  • 6
  • 48
  • 78
  • 1
    I take it all this code is in the same file? – fge Jun 09 '13 at 16:36
  • Yes, all code is in same file. – Lokesh Jun 09 '13 at 16:37
  • 2
    To me a private interface makes no sense at all, though the int being accessible is curious. – arynaq Jun 09 '13 at 16:39
  • 1
    An interface is by design a public contract, so where's the point in hiding it? – joerx Jun 09 '13 at 16:57
  • 1
    @joerx: How about a case where you dont want your contract to be visible to the world? – Lokesh Jun 09 '13 at 17:14
  • Well, this is what you are obviously trying to do, but I yet fail to find any use case for this. If you don't want to show it to the world, you could as well do without the contract in the first place. A package local interface would somehow make sense to me, but a completely private interface? – joerx Jun 09 '13 at 18:00

4 Answers4

2

Your member interface is private. The inherited static field is not private.

A private member interface cannot be used as a type outside the enclosing top-level class or enum. This can be useful to prevent external code from implementing an interface you may wish to change. From the JLS:

The access modifiers protected and private pertain only to member interfaces within a directly enclosing class or enum declaration (§8.5.1).

The interface field is public, and inherited by the class that implements the interface. From the JLS:

A class inherits from its direct superclass and direct superinterfaces all the non-private fields of the superclass and superinterfaces that are both accessible to code in the class and not hidden by a declaration in the class.

If you want to make the field accessible only within the classes that implement the member interface, you can put its declaration in the enclosing top-level scope.

class TestingInterfaceClass {
    private static final int i = 0;

    private interface InnerInterface {
        // ...
    }

    class inner implements InnerInterface {
        // ...
    }

}

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • And there is no possibility of making the field private, isn't it? So we should not be having private interfaces. Do you agree? – Lokesh Jun 09 '13 at 17:18
  • Private member interfaces are legal and useful. You can prevent external implementations, which allows you to change the interface as required without breaking code external to the top-level class. The inheritance of the field is a separate issue from the accessibility of the type. – Andy Thomas Jun 09 '13 at 17:20
  • I agree with your points but interface allows us to hide only methods and there is no way we can hide any variables information in interface. Doesn't it mean interfaces are never truly private? and are semi private. – Lokesh Jun 09 '13 at 17:29
  • The private qualifier on an interface restricts access to the *type*, not the methods or fields, which are both implicitly public. (BTW, see the edit above for how to avoid making the private field accessible outside TestingInterfaceClass.) – Andy Thomas Jun 09 '13 at 17:35
1

As I see, it is not the problem with private interface InnerInterface. It is the inner class which is at default scope inside TestingInterfaceClass exposing the content of InnerInterface. If you don't want the content of InnerInterface to be known to the world, you should also declare all the classes (specifically TestingInterfaceClass) as private.

Because every variable in an interface is public static final, it should be the responsibility of the class (implementing it) whether it should take care of the content inherited from private interface

Chris
  • 5,584
  • 9
  • 40
  • 58
  • Lets say i had a private innerclass with a private variable. Now if i create an innerclass with default scope then private variable will not be accessible, isn't it? But in interface it is still accessible. Does it mean interfaces should never be private? It should not be responsibility of innerclass to take care of this. – Lokesh Jun 09 '13 at 17:08
  • As you said, `private` members are never visible outside the class. But `public` members are. It is as simple as saying that if you inherit a `public` member (from a `class` or `interface`), it is visible through you. You cannot inherit a `private` member from `class` and `interface` doesnot have `private` members. If your question boils down to why `public static final` for all variables of `interface` check http://stackoverflow.com/questions/2430756/why-are-interface-variables-static-and-final-by-default – Chris Jun 09 '13 at 17:22
1

Even though it's allowed, we don't need (and shouldn't use) an instance to access an static field.

Following is the way to access it -

System.out.println(TestingInterfaceClass.inner.i);
//note you cannot access the InnerInterface like this here because it's private 

The inner has inherited the public static field i and i should be visible wherever the inner itself is visible.

Usually, interfaces are used to expose the behaviors of an object, while the implementations are hidden. But in your case, you are attempting the opposite.

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
0

The Interface variables are implicitly public static final, but you can't reach this variables because you can't reach previously the interface that contains these variable, which you have declared as private. First you need to be able to see the interface, and after that, go into content of the interface.

  • true but as you can see in the code that i am able to bypass that private interface using innerclass and access that variable. So whole point is why have private interface? – Lokesh Jun 09 '13 at 16:45