7

I created instance of base class in derived class and tried to access protected members.

I can directly access protected members in a derived class without instantiating the base class.

Base class:

package com.core;

public class MyCollection {

      protected Integer intg;
}

A derived class in the same package -

package com.core;

public class MyCollection3 extends MyCollection { 

 public void test(){

  MyCollection mc = new MyCollection();
  mc.intg=1; // Works
 }
}

A derived class in a different package -

package secondary;

import com.core.MyCollection;

public class MyCollection2 extends MyCollection{ 

 public void test(){
  MyCollection mc = new MyCollection();
  mc.intg = 1; //!!! compile time error - change visibility of "intg" to protected
 }
}

How it is possible to access a protected member of a base class in a derived class using instance of base class when derived class is also in same package but not when derived class is in different package?

If I mark protected member as "static" then I am able to access protected member of base class using instance of base class in a derived class which resides in a different package.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Tarun
  • 3,456
  • 10
  • 48
  • 82
  • possible duplicate of [Java Protected Access Not Working](http://stackoverflow.com/questions/332920/java-protected-access-not-working) --- Actually that's the wrong dupe! Sorry! This is definitely a dupe though. – polygenelubricants Jun 30 '10 at 11:25
  • don't worry, your IDE won't make any difference to the question as this is about the semantics of the Java language itself. – Andrzej Doyle Jun 30 '10 at 11:29
  • 1
    possible duplicate of [why can't i access protected java method even thought i've extended the class?](http://stackoverflow.com/questions/1622219/why-cant-i-access-protected-java-method-even-thought-ive-extended-the-class) – starblue Jun 30 '10 at 11:36

6 Answers6

11

You're right that you can't do this. The reason why you can't access the field, is that you're not in the same package as the class, nor are you accessing an inherited member of the same class.

The last point is the critical one - if you'd written

MyCollection2 mc = new MyCollection2();
mc.intg = 1;

then this would work, as you're changing a protected member of your own class (which is present in that class through inheritance). However, in your case you're trying to change a protected member of a different class in a different package. Thus it should come as no surprise that you're denied access.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • This explanation is really easy to understand. I had a look at java language specification and their elaboration went over my head!!! – Tarun Jul 01 '10 at 03:45
  • 1
    @Tarun - if an answer has worked for you, mark it as accepted (tick below the vote counter) – Bozho Jul 01 '10 at 11:45
  • I did not know this feature. I would mark it as answered now. – Tarun Jul 02 '10 at 05:41
  • @Doyle I think this answer does make sense, but you might ignore that why we can access mc.intg if we make intg static in MyCollection – Gin Aug 05 '11 at 01:43
3

If a class member is protected then there are 2 cases:

  1. If subclass is in same package
  2. If subclass is in different package

I. Same package :
- Can access through inheritance
- Can access by creating an instance of parent class
II. Different package :
- Can only access through inheritance

See the table below for all use cases:

enter image description here

Source: SCJP book.

Ram Patra
  • 16,266
  • 13
  • 66
  • 81
3

The Java tutorial says:

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.

And in your case, you are accessing the variable in another object. By coincidence it has a class that's the same as the current one, but the visibility checks wouldn't check that.

So, the second time you are denied access, because you are in a different package, and the first time you are given access because you are in the same package (and not because it's a subclass)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • "first time you are given access because you are in the same package (and not because it's a subclass)" This makes it clear for me. Thanks. – Tarun Jul 01 '10 at 03:47
1

In short, it's not really possible. It seems like you should reconsider your design.

However, there's a work around, if you're sure that's what you want to do. You can add a protected method to MyCollection which takes an instance and sets the value of intg on your behalf:

package com.core;

public class MyCollection {

    protected Integer intg;

    protected void setIntg(MyCollection collection, Integer newIntg) {
        collection.intg = newIntg;
    }
}

Now your subclasses can access this method:

package secondary;

import com.core.MyCollection;

public class MyCollection2 extends MyCollection{ 

    public void test(){
        MyCollection mc = new MyCollection();
        setIntg(mc, 1);
    }
}

But please note that this is a very strange way of doing it. I'd suggest again that your design needs to be rethought before you go down this route.

Chris
  • 10,337
  • 1
  • 38
  • 46
  • I get your point. Most easy way for me would have been to directly access the protected member than instantiating base class and accessing it in a different package. I did it "mistakenly" while playing with java (did not I say I have been a manaul tester :-)) and then none of my dev member was able to provide me conceivable answer. So I posted it here. – Tarun Jul 01 '10 at 03:50
0

You cant access a protected variable in a derived class (which is in different package) if accessed using a new object of class MyCollection. you can just write intg = 1; directly without making ( new MyCollection ) like this:

package secondary;
import com.core.MyCollection;       
public class MyCollection2 extends MyCollection{ 

 public void test(){

     intg = 1;

 }
}
Hamzeh
  • 167
  • 1
  • 4
  • 13
0

According to the member accessibility rule of Java you cannot access protected member of a class without extending it.

You can try the following.

package secondary;

import com.core.MyCollection;

public class MyCollection2 extends MyCollection{ 

 public void test(){
  intg = 1; 
 }
}

Instead of creating the new instance try to assign the value. It will work.

Puru
  • 8,913
  • 26
  • 70
  • 91