I\'m reading Sybex Complete Java 2 Certification Study Guide April 2005 (ISBN0782144195). This book is for java developers who wants to pass java certification.
True or false: If class Y extends class X, the two classes are in different packages, and class X has a protected method called abby(), then any instance of Y may call the abby() method of any other instance of Y.
Let's depict it.
Class X:
package one;
public class X {
protected void abby() {}
}
Class Y:
package other;
public class Y extends X {}
Testcase:
public static void main(String[] args) {
Y y1 = new Y();
Y y2 = new Y();
Y y3 = new Y();
// ...
}
Now reread the question: can y1
call abby()
on y2
, y3
, etc? Will calling abby()
on y1
also call those of y2
, y3
, etc?
For future questions, try to grab pen and paper and interpret the questions literally. There are pretty much holes in those kind of mock questions.
True or false: If class Y extends class X, the two classes are in different packages, and class X has a protected method called abby(), then any instance of Y may call the abby() method of any other instance of Y.
"False. An object that inherits a protected method from a superclass in a different package may call that method on itself but not on other instances of the same class".
Let's write that down, as BalusC did, and add to Y a method which calls the abby() of any other instance of Y:
package one;
public class X {
protected void abby() {
}
}
package other;
import one.X;
public class Y extends X {
public void callAbbyOf(Y anyOther) {
anyOther.abby();
}
}
It is possible for Y to call the abby() method of any instance of Y to which it has a reference. So the answer in the book is blatantly wrong. Java does not have instance-specific scopes (unlike for example Scala which has an instance-private scope).
If we try to be merciful, maybe the question meant by saying "any other instance of Y" that can it access the method of any instance of Y which happens to be in memory - which is not possible, because Java does not have direct memory access. But in that case the question is so badly worded, that you could even answer: "False. You can not call methods on instances which are on a different JVM, or instances which have been garbage collected, or instances on a JVM which died one year ago etc."
Because variable type is irrelevant here till it is 'sane' in context of question. As method abby()
belongs to X
(and Y
inherits it), it doesn't matter with what type variable referencing instance of Y is declared: it can be either X
or Y
. Be abby()
accessible, we could call it through both variables:
X myY1 = new Y();
myY1.abby();
Y myY2 = new Y();
myY2.abby();
I am almost certain that the question meant:
"any instance of Y may call the abbey() method of any other instance of X" (not Y).
In that case it will indeed fail. To borrow the example from another answer above, the following:
package one;
public class X {
protected void abby() {
}
}
package other;
import one.X;
public class Y extends X {
public void callAbbyOf(X anyOther) {
anyOther.abby();
}
}
will fail to compile.
The Java Language Specification explains why here: http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.2
6.6.2.1 Access to a protected Member
Let C be the class in which a protected member m is declared. Access is permitted only within the body of a subclass S of C. In addition, if Id denotes an instance field or instance method, then: If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S. If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S. (emphasis mine).
From The Java Language Specification:
6.6.2.1 Access to a protected Member
Let C be the class in which a protected member m is declared. Access is permitted only within the body of a subclass S of C. In addition, if Id denotes an instance field or instance method, then:
So the protected member is accessible in all instances of S, and the answer in your book is just wrong.
That question seems badly worded - and asks about a very rare edge case (that I'm not even sure is covered on the SCJP test). The way that it's worded makes your answer correct and the given answer incorrect. Coding a similar construct and running it easily proves this...
package inside;
public class Base {
private String name;
public Base(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
protected String abby(String name) {
String old = this.name;
this.name = name;
return old;
}
}
package outside;
import inside.Base;
public class Another extends Base {
public Another(String name) {
super(name);
}
public String setAnother(Another another, String hack) {
return another.abby(hack);
}
public static void doCrazyStuff() {
Another one = new Another("one");
Another two = new Another("two");
one.abby("Hi one");
two.abby("Hi two");
one.setAnother(two, "Hi two from one");
System.out.println("one = " + one.getName());
System.out.println("two = " + two.getName());
}
public static void main(String[] args) {
Another.doCrazyStuff();
}
}