17

In his book, Herbert Schildt says in page 172 (3rd paragraph) that "protected applies only when inheritance is involved.".

In page 228, Table 9-1 shows that a protected member can be accessed from a non-sub class within the same package.

The following code works and supports the information in Table 9-1.

Class1.java:

package Mypack;
public class Class1
{
    protected pro=1;
    public Class1()
    {
        System.out.println(pro);
    }
}

Class2.java

package Mypack;
class Class2 extends Class1
{
    Class2()
    {
        System.out.println(pro);
    }
}

Class3.java

package Mypack;
class Class3
{
    Class3()
    {
        Class1 class1=new Class1();
        System.out.println(class1.pro);
    }
}

It is alright that the variable pro can be accessed from the derived class Class2. But how can it be accessed from the non-derived class Class3 through a reference to an object of Class1? It contradicts the statement on page 172. If it is so, then I find no difference between the public and protected specifiers in this situation.

psmears
  • 26,070
  • 4
  • 40
  • 48
PS Nayak
  • 409
  • 8
  • 20

5 Answers5

20

In his book, Herbert Schildt says in page 172 (3rd paragraph) that "protected applies only when inheritance is involved.".

There's an argument that that statement is correct, although I'd say it's quite misleading. Let's look at the access chart from the access control tutorial:

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

Note that no modifier grants both class and package access to the member, and does not grant access to subclasses or the world. protected only changes one of those things: It makes the member available to subclasses. So in that sense, he's correct: It only applies when inheritance is involved; without inheritance, it's the same as having no modifier.

But I find it quite misleading, for the very reason that inspired your question: It seems to imply that there won't be package access. The only way the statement makes sense is if you already know that no modifier grants package access.

For clarity: protected means a member is available to any class in the package and to code in subclasses. Doing this makes it possible for a library to have fields and methods you only access from code that's part of the library* (sort of, see below) or code that helps implement something in the library (for instance, if you're subclassing from one of the library classes). There's no particular "why" other than that's how the language was designed.

If it is so, then I find no difference between the public and protected specifiers in this situation.

In this situation, no. There's obviously quite a large difference, though, when you consider code that isn't in the same package and isn't in a derived class of a package member: That code has no access to protected members.

This is covered in JLS§6.6.1:

...if the member or constructor is declared protected, then access is permitted only when one of the following is true:

  • Access to the member or constructor occurs from within the package containing the class in which the protected member or constructor is declared.

  • Access is correct as described in §6.6.2.

(note the first bullet) and JLS§6.6.2:

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

("code that is responsible for the implementation of that object" — e.g., code in a subclass.)


* Re my "sort of, see below" on "Doing this makes it possible for a library to have fields and methods you only access from code that's part of the library..." That's not really true, because except for the restricted packages (java.lang, for instance), you can happily write your own class saying it's in the library's package, and then use the package level fields and methods of the library's classes. Java's package concept is not a field/method security mechanism.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
4

The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package. https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

connexo
  • 53,704
  • 14
  • 91
  • 128
3

Something that is declared protected is visible to itself, its children, and the package it's declared in.

If Class3 were in a different package, like mypack.nested, then you wouldn't be able to access class1.pro at all.

Makoto
  • 104,088
  • 27
  • 192
  • 230
1

The table on this link shows the modifiers versus what http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html can be accessed. Modifier is then chosen base on factors like what needs to be hidden to other class what needs to be shared according to good principles like encapsulation etc

Access Levels

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

1

If it is so, then I find no difference between the public and protected specifiers in this situation

That is correct, there is no difference in that situation.
Consider this code :

package otherpack;
public class Class4
{
    Class4()
    {
        Class1 class1=new Class1(); // Ok, Class1 and it's constructor are public
        System.out.println(class1.pro); // Compilation error. pro is protected
    }
}

package otherpack;
public class Class5 extends Class1
{
    Class5()
    {
        Class1 class1=new Class1(); // Ok, Class1 and it's constructor are public
        System.out.println(class1.pro); // OK, Class5 extends Class1 and pro is protected
    }
}

In the situation of code in a different package public and protected are different. You can use public members from different packages but not protected members unless you do so in a derived class.

Anonymous Coward
  • 3,140
  • 22
  • 39