Scope of protected members - java

Iam preparing for SCJP , also i came to know that protected members scope is within the package as well as in other package with some conditions like possible only with inheritance.
For example :
i have three classes as Parentclass Childclass Friendclass
package x.parent;
class Parentclass{
protected int x=10;
...............
}
package x.child;
class Childlass extends Parentclass{
super.x=20;
...............
}
package x.child;
import x.parent.Parentclass;
class Friendclass{
Parentclass pc = new Parentclass();
pc.x=30;
...............
}
Whats the reason behind that, in Friendclass the member x will not accept to assign a value to that, behaves as private member not in case of Childclass.

There are four access modifiers
private - just this class
no modifier - just this class or this package (NOT subclass)
protected - just this class, this package, or subclass
public - everyone and their cousin
Since it uses the default modifier, it has access if one of the following is true:
Is part of the class itself (Nope!)
Is part of the package of the class itself (Nope!)
So it fails the criteria, and so you don't get access.

You can't even access Parentclass.x in Childclass because x has default visibility (not protected). See http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
edit:
x.child.Friendclass is not in the same package as x.parent.Parentclass.
x.child.Friendclass does not inherit from x.parent.Parentclass.
as TotalFrickinRockstarFromMars's summary states and the Java access control docs also state, this means that Friendclass is not allowed to access the field x.

Related

'public' class exposes its 'public/*package*/' superType xxxClass [duplicate]

I have the following Java and Kotlin classes:
package nl.friesoft.solaredgenotifier;
class SolarEdgeException extends Exception {
public SolarEdgeException(String s) {
super(s);
}
}
package nl.friesoft.solaredgenotifier
class SiteStorage(context: Context): ISolarEdgeListener {
override fun onError(site: Site?, exception: SolarEdgeException?) {
}
}
And I get this compilation error:
'public' function exposes its 'public/package/' parameter type SolarEdgeException
Both classes are in the same package, so why doesn't this compile?
Classes by default in Kotlin are public, so every member/function is exposed to the outer world. Contrarily, in Java the default visibility, that is omitting a visibility keyword such as public, protected or private, is package-private.
SolarEdgeException is package-private, while its user SiteStorage is entirely public.
That means a user of SiteStorage cannot catch or use your exception at all.
Unfortunately Kotlin doesn't have the concept of package-private, because packages aren't managed the same way as in Java.
The best you can have is internal, which means the definition is visibile to the entire module.
I'd say, in this case, make SolarEdgeException a public class, maintaining the constructor as package-private.
There is a forum thread on the package-private visibility for Kotlin, it's an interesting read. kotlin-to-support-package-protected-visibility

'public' function exposes its 'public/*package*/' parameter type SolarEdgeException

I have the following Java and Kotlin classes:
package nl.friesoft.solaredgenotifier;
class SolarEdgeException extends Exception {
public SolarEdgeException(String s) {
super(s);
}
}
package nl.friesoft.solaredgenotifier
class SiteStorage(context: Context): ISolarEdgeListener {
override fun onError(site: Site?, exception: SolarEdgeException?) {
}
}
And I get this compilation error:
'public' function exposes its 'public/package/' parameter type SolarEdgeException
Both classes are in the same package, so why doesn't this compile?
Classes by default in Kotlin are public, so every member/function is exposed to the outer world. Contrarily, in Java the default visibility, that is omitting a visibility keyword such as public, protected or private, is package-private.
SolarEdgeException is package-private, while its user SiteStorage is entirely public.
That means a user of SiteStorage cannot catch or use your exception at all.
Unfortunately Kotlin doesn't have the concept of package-private, because packages aren't managed the same way as in Java.
The best you can have is internal, which means the definition is visibile to the entire module.
I'd say, in this case, make SolarEdgeException a public class, maintaining the constructor as package-private.
There is a forum thread on the package-private visibility for Kotlin, it's an interesting read. kotlin-to-support-package-protected-visibility

Bug in android studio? Can't access protected member in sub-class

Look, PlanetShape extends Shape!
And yet it says isOverlapMethodLevel have protected access in Shape!
Did I just discovered a bug in android studio? Or is it something else?
The packages differ in your class hierarachy - specifically your PlanetShape class is in a different package to the classes it extends.
Directly from Java documentation: (emphasis mine)
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.
Clearly the "by a subclass of its class in another package" seems to be the cause of some confusion and I agree that the wording is rather ambiguous.
Basically, what they're trying to say is you can do this:
public class PlanetShape extends Shape {
aMethod() {
// call the protected method declared in the Super class (ok)
doProtectedMethodOfShape();
}
}
But not this:
public class PlanetShape extends Shape {
aMethod() {
Shape s = new Shape();
s.doProtectedMethodOfShape(); // error here
}
}
In the second example, you get an error because you're not accessing a protected method via inheritance, you're just trying to access a protected member function from an instance in another package.

In what context are statements in Java interface definitions executed?

I'm looking at the definition of org.apache.maven.plugin.Mojo:
public interface Mojo
{
String ROLE = Mojo.class.getName();
[...]
}
I'm lost. To my knowledge, Java interfaces are a set of method signatures. So what's this line which looks like a statement doing here? What are the semantics? For example:
When does that line get "executed"?
In the context in which that line runs, what does Mojo refer to? What is its type?
In the context in which that line runs, what does Mojo.class refer to? I assume its type is java.lang.Class?
In what context can I read that ROLE variable? What is the syntax for doing so? What will the variable contain?
Can I write to that ROLE variable?
All the fields of an interface are implicitely public, static and final. So this is the same as writing
public static final String ROLE = Mojo.class.getName();
It defines a constant, that all the users of the interface can use, as any other constant: Mojo.ROLE. This line is executed when the Mojo interface is initialized by the ClassLoader. Mojo.class is the Mojo class, indeed of type java.lang.Class<Mojo>. Since the package of the class is org.apache.maven.plugin, the value of the constant will be "org.apache.maven.plugin.Mojo".
Look here for the relevant section of the Java language specification.
the variable get defined when class loader loads the class.
interface variables are static final and can be accessed statically by any class that implements the interface.
public class MyClass implements Mojo{
.
.
.
}
access:
public void someMethod(){
System.out.println(MyClass.ROLE)
}
All fields in an interface are implicitly static and final. That answers some of your questions:
The line gets executed during the static execution. That is possibly during compilation, possibly at the launching of the program and possibly when the class loader loads that class. It's a complicated business, but it's the same as all other static fields.
Mojo refers to the interface itself, statically. It is a type itself, so it has no type.
Mojo.class refers to the java.lang.Class of Mojo.
You can read the ROLE variable in any class that implements Mojo. You can only read it statically, like Mojo.ROLE.
No, the field is final, so you can't write to it. It is intended for constants only.
When does that line get "executed"?
Any member of an Interface is static and final by default, so String ROLE (which can effectivly be seen as
public static final String ROLE
will be initialized, as every static member, when the ClassLoader loads the class (by the first time, the class is referenced).
JLS - Loading of Classes and Interfaces
In the context in which that line runs, what does Mojo refer to? What is its type?
In the context in which that line runs, what does Mojo.class refer to? I assume its type is java.lang.Class?
Mojo is of the type java.lang.Class<Mojo>
In what context can I read that ROLE variable? What is the syntax for doing so? What will the variable contain?
As it is implicit public static final you can access it from everywhere by using Mojo.ROLE or through the implementing classes by ClassName.ROLE. As Class#getName() says in the java doc, it will contain the full qualified name of the object:
org.apache.maven.plugin.Mojo
Can I write to that ROLE variable?
No, you cannot, because it is implicit final
JLS - Interfaces

Protected member behavior once it was inherited.

I've got some doubts regarding protected identifier. In the first chapter of Sun Certified Java Programmer Study Guide by K.Sierra I found the following information:
"Once the subclass-outside-the-package inherits the protected member, that member (as inherited by the subclass) becomes private to any code outside the subclass, with the exception of subclasses of the subclass."
I provided sample code which reflects the above statement and it is absolutely clear to me.
// Parent class
package package1;
import package2.Child;
public class Parent {
protected int i = 5;
}
// Child class
package package2;
import package1.Parent;
public class Child extends Parent {
// variable 'i' inherited
}
package package2;
public class Neighbour {
public void protectedTesting(){
Child child = new Child();
System.out.println(child.i); // no access
}
}
I've started experimenting and made a small change - moved Neighbour to package1. And there is an access to "i" variable which is a little bit surprising for me as it is not in accordance to statement "becomes private to any code outside the subclass"
Neighbour class after change:
package package1;
import package2.Child;
public class Neighbour {
public void protectedTesting(){
Child child = new Child();
System.out.println(child.i); // access!
}
}
Please clarify it to me. Thanks.
In short, protected is package-private as well as visible to subclasses. Even the JLS is vague on this (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.
It specifies that outside the package, only subclasses can access protected members. This implies that you can also access the variable within the package. It's poor wording, but true nonetheless that protected members have package-level visibility as well as subclass-level visibility.
See also:
This related question
The Java Trail for access control
And there is an access to "i" variable which is a little bit surprising for me as it is not in accordance to statement "becomes private to any code outside the subclass"
--> But you moved class Neighbour in package package1 which is true according to "Protected members can be accessed by classes in same package"
"Once the subclass-outside-the-package inherits the protected member, that member (as inherited by the subclass) becomes private to any code outside the subclass, with the exception of subclasses of the subclass."
--> Inside package it is still protected and not private for all classes within the package.
The truth is not in "Sun Certified Java Programmer Study Guide" but in the Java Language Specification
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.
protected visibility includes package level visibility.
Inheritance allows you to treat your Child object as an instance of Parent.
As the member i of Parent is declared in the same package, it is accessible from Neighbour.
package package1;
import package2.Child;
public class Neighbour {
public void protectedTesting() {
Parent neighboured = new Child();
System.out.println(neighboured.i); // access
}
}

Categories

Resources