A Possibly Silly Question about Java Visibility
Thursday, December 20, 2018 |This morning, I was asked a question by a coworker that we both thought we knew
the answer to: if a method is protected
, can other classes see that method? The
answer surprised us: maybe. :) It’s a pretty simple, basic question, but I thought
I’d mention it in case there’s a beginner wondering, or more senior developers, such
as myself and my team mate, that just have it wrong. :)
The official Java docs provide a nice chart, which I’ve reproduced here:
Modifier | Class | Package | Subclass | World |
---|---|---|---|---|
public |
Y |
Y |
Y |
Y |
protected |
Y |
Y |
Y |
N |
no modifier |
Y |
Y |
N |
N |
private |
Y |
N |
N |
N |
What we knew was that protected
members were visible to subclasses. What we
expected, though, was they would not be visible to any other classes. What we
found accidentally when writing tests, and what the table clearly indicates, is
that the method is visible to classes in the same package. To demonstrate, I
cobbled together a simple project:
1
2
3
4
5
6
7
8
9
package com.steeplesoft.visibilitytest;
public class Class1 {
public void publicMethod() { }
protected void protectedMethod() { }
private void privateMethod() { }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.steeplesoft.visibilitytest;
public class Class2 {
public Class1 publicInstance = new Class1();
protected Class1 protectedInstance = new Class1();
private Class1 privateInstance = new Class1();
public void publicMethod() {
publicInstance.publicMethod();
publicInstance.protectedMethod();
publicInstance.privateMethod(); // Error - not visible
}
protected void protectedMethod() { }
private void privateMethod() { }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.steeplesoft.visibilitytest.sub;
import com.steeplesoft.visibilitytest.Class1;
import com.steeplesoft.visibilitytest.Class2;
public class Class3 {
public Class1 class1 = new Class1();
protected Class2 class2 = new Class2();
public void publicMethod() {
class1.publicMethod();
class2.publicMethod();
class1.protectedMethod(); // Error - not visible
class1.privateMethod(); // Error - not visible
class2.protectedMethod(); // Error - not visible
class2.privateMethod(); // Error - not visible
class2.secondInstance(); // Error - not visible
class2.thirdInstance(); // Error - not visible
}
}
As expected (for those sharper than I, it seems), Class2 can see Class1.publicMethod
and Class1.protectedMethod
,
but not Class1.privateMethod
. Class3
, however, can only see Class2.publicMethod
,
but not the other two. It can also only see the publicInstance
field, but neither
protectedInstance
nor privateInstance
.
Moral of the story: if you’re trying to hide methods from other classes, protected
may not be the answer your looking for.