user2250448
user2250448

Reputation: 3

Visibility of protected field

package p1;

public class MyClass1 {

      protected static  String str = "ss1";

    }

package p2;

import p1.MyClass1;

public class MyClass2 extends MyClass1 {

     public static void test(){

         MyClass1 mc1 = new MyClass1();

         System.out.println(mc1.str); 

         }

}

As I understand it, the print statement will not work if the String is declared as protected as it is not visible from a different package. But why does it work when is declared as static protected ?

Upvotes: 0

Views: 1059

Answers (5)

Grzegorz Olszewski
Grzegorz Olszewski

Reputation: 1428

static modifier has nothing to do with visibility, so nothing will change. You can't access protected member (i.e. field, method) from different package, no matter if it's static or not.

But in your case, MyClass2 extends MyClass1. You can access protected members from superclass. Still, static has nothing to do with this.

EDIT:

Well, this is a very interesting case because there are involved two separate things: 1) Accessing protected members from subclass in different package, 2) Syntax trick allowing you to access static (class) members like instance members.

I will extend your example to show what actually are you doing in this code:

package p1;

public class MyClass1 {

    protected String protectedString = "example";

    protected static String protectedStaticString = "example";

}

package p2;

import p1.MyClass1;

public class MyClass2 extends MyClass1 {

    public void testProtected() {

        MyClass1 otherMC1 = new MyClass1();
        MyClass2 otherMC2 = new MyClass2();

        String testProtected;

        testProtected = this.protectedString; // OK, protectedString is inherited, so it's instance member of this class
        testProtected = super.protectedString; // OK, it's also instance member of superclass

        testProtected = otherMC1.protectedString; // ERROR. You can't access protected members of other instance of superclass
        testProtected = otherMC2.protectedString; // OK. As it's inherited member of MyClass2, you can access it if it belongs to other instance of your class

    }

    public void testProtectedStatic() {

        MyClass1 otherMC1 = new MyClass1();
        MyClass2 otherMC2 = new MyClass2();

        String testProtectedStatic;

        testProtectedStatic = this.protectedStaticString; // OK - syntax trick
        testProtectedStatic = super.protectedStaticString; // OK - syntax trick

        testProtectedStatic = otherMC1.protectedStaticString; // OK - syntax trick
        testProtectedStatic = otherMC2.protectedStaticString; // OK - syntax trick

        testProtectedStatic = MyClass1.protectedStaticString; // OK - you can access protected static members from superclass
        testProtectedStatic = MyClass2.protectedStaticString; // OK - this also static member of your class
    }

}

Now, what is 'syntax trick'. Compiler allows you accessing static members like they were instance members:

MyClass mc = new MyClass();
Object o = mc.STATIC_FIELD;

But what will be actually compiled to the bytecode:

MyClass mc = new MyClass();
Object o = MyClass.STATIC_FIELD;

Accessing static members in this way is considered as bad practice because it's misleading. You should always access static members in a static way to avoid confusion while reading code.

This is what's goin on in your case. There were static field accessed in a non-static way, so it looked like instance field. When you removed static modifier, it became an instance member. The way this field is accessed changed, but you didn't notice that because of your object.staticField syntax.

Upvotes: 3

blackpanther
blackpanther

Reputation: 11486

Here is an interesting rule: You can access protected instance variables defined in a superclass, but you cannot access private instance variables in a subclass of that class with the private instance variables. e.g.

public class Super {
   private String str;
}

public class Sub extends Super {
    public void getStr(){
        return str; // not allowed.
    }
}

However, if the following was used, then this is allowed:

public class Super {
   protected String str;
}

public class Sub extends Super {
    public void getStr(){
        return str; // allowed.
    }
}

Upvotes: 0

Lone nebula
Lone nebula

Reputation: 4878

  • public means it's visible to all classes.
  • protected means it's visible to the package and all sub-classes.
  • (no modifier) means it's visible to the package only.
  • private means it's only visible in its own class.

See Controlling Access to Members of a Class for more info.

Upvotes: 0

vptheron
vptheron

Reputation: 7476

As pointed out, static has nothing to do with visibility.

In your case, 'str' is marked as protected, which means that 2 types of classes can see it : - classes in the same package - classes that extend MyClass1

Your code works because MyClass2 extends MyClass1.

Upvotes: 1

Rodrigo Sasaki
Rodrigo Sasaki

Reputation: 7236

It has nothing to do with it being static or not. you can access the member because MyClass2 extends MyClass1

Upvotes: 0

Related Questions