简体   繁体   中英

Accessing a protected variable from a subclass outside package

I have gone through so many websites which explains about access specifiers in java such as java papers , java's access specifiers , and many other stackoverflow questions like here .

All these guys explained that the protected member can be accessed by any subclass(also by the subclass out of package) and can be accessed by the package level classes.

While experimenting on protected members, I found out that I'm unable to access a protected member from a subclass outside package.

Check the code below. A public class with protected members:

package com.One;

    public class ProVars {

    protected int i = 900;

    protected void foo()
    {
        System.out.println("foo");
    }

}

Another public class in different package trying to access protected member:

package com.Two;

import com.One.ProVars;

public class AnotherClass extends ProVars {

    public static void main(String[] args) {
        ProVars p = new ProVars();
        System.out.println(p.i);//the field ProVars.i is not visible(Compilation Error)
                p.foo();//the method foo() from the type ProVars is not visible

    }
}

Any explanation is appreciated.

You're attempting to use them as if they were public . They are not public , they are protected .

ProVars p = new ProVars();
p.foo(); // This will throw an error because foo() is not public.

The correct usage, for a subclass to use a protected method or variable is:

public class MyClass extends ProVars
{
     public MyClass()
     {
           System.out.println(i); // I can access it like this.
           foo(); // And this.
     }
}

Why does this work?

Because you've inherited the class. That means you've got all of its methods and it's variables. Now, because your method and variable is protected , it also means that it can be accessed from the subclass . Try and declare them as private and see what happens.

Even inside a derived class, you can only access a protected field from a qualifier that is at least of your own type .

Inside AnotherClass , you can access new AnotherClass().i , but not new ProVars().i .

It would be fine if your main method wasn't static. Static methods don't care about inheritance hence your "extends ProVars" is not going to work. This on the other hand should work:

public class AnotherClass extends ProVars {

   public void accessProtected() {
       System.out.println(this.i);
       this.foo();
    }

    public static void main(String[] args) {
        AnotherClass p = new AnotherClass();
        p.accessProtected();
    }

}

Confusion with Java protected access is caused by the wrong tutorial: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

Reading the tutorial even several times doesn't give a clue, why you cannot access protected member of an object of class Alpha from another object of another package, whose class AlphaSub is a subclass of Alpha .

Actually, Java Language Specification explains this, eg in JLS 8:

6.6.2 Details on protected Access

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 .

You need to change the line ProVars p = new ProVars(); into AnotherClass p = new AnotherClass();

Otherwise, you're still creating an object of type ProVars, and the compiler won't be able to realise the inheritance between AnotherClass and ProVars (which leads to the compilation error).

Use the subclass In your main() :

public class AnotherClass extends ProVars {

    public static void main(String[] args) {
    AnotherClass p = new AnotherClass();
    System.out.println(p.i);
            p.foo();

}

}

When we say it is available from subclass, we mean it is available to subclass code. But in your example you are calling protected method from outside.

So while your example does not work, this should

package com.Two;

import com.One.ProVars;

public class AnotherClass extends ProVars {

public static void main(String[] args) {
    ProVars p = new ProVars();
    p.test();
}

public test() {
        System.out.println(this.i);)
        this.foo();
}



}

Your code accessing the variables is inside a static method - the static method is not directly part of an object that inherits the protected fields.

Try moving the code to a method inside your AnotherClass class and then calling that method from your static method.

Members declared protected in a class in one package is inherited by subclass which could lie either in same package of the class or in different package.

**Here inherited means same protected member of super class is available in subclass, use of parent reference and dot operator to access like below will throw compilation error.

ProVars p = new ProVars();
System.out.println(p.i);// error: i has protected access in parent

simply use this in your subclass:

System.out.println(i); // works fine, since subclass inherit the protected 
                          member of super class no matter whether they are in 
                          same or different package.

Two Conditions Must Meet to access the protected field in the super class

1) protected and are accessible outside the package points only in subclasses of class

The second one is always be ignored that is

2) they are fields of objects that are being implemented by the code that is accessing them.

please refer to this JavaDocs https://docs.oracle.com/javase/specs/jls/se11/html/jls-6.html#jls-6.6.2

This is the way protected access modifiers works:

package a;

public class Fruit {
  protected int i = 5;
  protected void sayHello() {
    System.out.println("hello Fruit");
  }
}

Now importing the above like this :

package b;
import a.Fruit;

public class Banana extends Fruit {
  public static void main(String[] args) {

    Banana banana = new Banana();
    System.out.println(banana.i);   // 5
    banana.sayHello();              // hello Fruit

    Fruit fruit = new Fruit();
    System.out.println(fruit.i);    // compile error
    fruit.sayHello();               // compile error

    Fruit fb = new Banana();
    System.out.println(fb.i);       // compile error
    fb.sayHello();                  // compile error
  }
}

You have to use inheritance and in second package method you have to use system.Out.Println(this.Protected);

And in main method use creating object like Demopackage obj = new Demopackage(); Obj.Protected

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM