Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are java.lang.Object's protected methods protected from subclasses?

The keyword protected grants access to classes in the same package and subclasses (http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html).

Now, every class has java.lang.Object as superclass (http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html).

Hence I conclude that every class may access java.lang.Object's methods even if they are protected.

Take a look at the following example:

public class Testclass {
  public Object getOne() throws CloneNotSupportedException {
    return this.clone();
  }
  public Object getTwo() throws CloneNotSupportedException {
    return ((Object) this).clone();
  }
}

While getOne() compiles fine, getTwo() gives

Testclass.java:6: clone() has protected access in java.lang.Object
        return ((Object) this).clone();

I neither understand why getTwo() doesn't compile nor what's the difference (regarding the access of java.lang.Objects members) with getOne().

like image 250
Adrian Heine Avatar asked Jan 16 '09 19:01

Adrian Heine


People also ask

Can protected methods be accessed by subclasses?

protected allows you access from the same package, or parent classes. protected allows access within the same package, or by subclasses. Neither is the case when using a superclass object reference.

Can we use protected in subclass Java?

The protected Keyword While elements declared as private can be accessed only by the class in which they're declared, the protected keyword allows access from sub-classes and members of the same package.

Can a protected method called by an object?

Protected methods can be called on the object of subclass without overriding.

Why is the clone () method protected in Java Lang object?

clone() method is protected i.e. accessed by subclasses only. Since object is the parent class of all sub classes, so Clone() method can be used by all classes infact if we don't have above check of 'instance of Cloneable'.


2 Answers

You can only access protected members of a type in a different package if the compile-time type of the expression you're referencing it through is either your own class or a subclass. (Where "your" class is the class containing the code.) Your own class has to be a subclass of the type which originally declares the method, too.

Here's an example; assume that Base is in a different package to all the other classes:

package first;
public class Base
{
    protected void Foo() {}
}

// Yes, each class is really in its own file normally - but treat
// all the classes below as being in package "second"

package second;
public class Child extends Base
{
    public void OtherMethod(Object x)
    {
        ((Base) x).Foo(); // Invalid: Base is not Child or subclass
        ((Child) x).Foo(); // Valid: Child is Child
        ((GrandChild) x).Foo(); // Valid: GrandChild is subclass of Child
        ((OtherChild) x).Foo(); // Invalid: OtherChild is not Child or subclass
    }
}

public class GrandChild extends Child {}
public class OtherChild extends Base {}

In other words, it's letting you have access to the protected members of "objects which are a like you".

Details are in section 6.6.2 of the Java Language Specification:

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.

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.

like image 99
Jon Skeet Avatar answered Oct 28 '22 03:10

Jon Skeet


When you said "((Object) this).clone()", you accessed your own object via its superclass Object. You performed a widening conversion to an Object. The code then attempts to call clone on Object.

But, as you've noted, clone is a protected method, meaning that only if your object was in the same package of java.lang would it be able to access the OBJECT's clone method.

When you say this.clone, your class extended Object and thus had access to override or use clone directly through the protected class modifier because of inheritance. But that doesn't change the Object implementation.

By saying ((Object) yourObject), you get something that is only accessible through the Object class. Only public methods of the Object class are accessible ouside of the package java.lang, so you get the compile-time exception, because the compiler knows this.

By saying this.clone(), you are invoking your object's clone method that it got through inheriting through Object, and is now able to be invoked because it becomes a part of your custom subclass.

like image 30
MetroidFan2002 Avatar answered Oct 28 '22 03:10

MetroidFan2002