Java-java protected clone不能被子类调用

发布于 2016-10-30 20:48:37 字数 1021 浏览 1407 评论 3

public class CloneTest {
protected void doWhat() {
System.out.println("what...");
}
public static void main(String[] args) {
CloneTest ct = new CloneTest();
ct.doWhat();// compile ok
ChildClone cc = new ChildClone();
cc.doWhat();// compile ok
GrandsonClone ccc = new GrandsonClone();
ccc.doWhat();// compile ok

CopyObject co = new CopyObject();
co.clone();// compile error (1)
}
}
class CopyObject //extends Object //implements Cloneable
{
/*@Override
protected CopyObject clone() throws CloneNotSupportedException {
CloneTest ct = new CloneTest();
ChildClone cc = new ChildClone();

return (CopyObject) super.clone();
}*/ //去掉这个注释 (1)编译OK,而不管是否这个类implements Cloneable接口
}
class ChildClone extends CloneTest {}
class GrandsonClone extends ChildClone {}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

偏爱自由 2017-08-16 02:17:19

这个问题有点意思.

Oracle官方tutorial这么说:

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.
-- http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
好像protected只要是同一包内, 或者子类里即可访问. 实际上这是不准确的, 有误导性.

JLS7 上是这么说的:

"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."

同时在JLS7上有差不多的例子, 针对此问题我做了点简化:

//JLS7, Example 6.6.2-1.
package points;
public class Point {
protected int x, y;
}

package threePoint;
import points.Point;
public class Point3d extends Point {
public void delta(Point p) {
p.x += this.x; // compile-time error: cannot access p.x
p.y += this.y; // compile-time error: cannot access p.y
}
}

注意在子类Point3d里, 无法访问父类的实例来访问 protected 成员. 因为
"while Point3d (the class in which the references to fields x and y occur) is a subclass of Point (the class in which x and y are declared), it is not involved in the implementation of a Point (the type of the parameter p)."

回到楼主的问题

可以看到protected是按照对象实例做访问控制的. 即

CopyObject co = new CopyObject();
co.clone();

这里对象实例co 的clone()方法只能在实现co的代码中调用, 即只能在类CopyObject 中调用.

最后给出自己的小例子:

package bbb;
public class A {
protected void a(){}
}

package aaa;
import bbb.A;
class B extends A{
static void x(){
new B().a();//这里可以
}
}

class C extends A{
void x(){
new B().a();//编译错,The method a() from the type A is not visible
}
}

偏爱自由 2017-01-30 20:39:57

大致明白了,我把它梳理补充点总结如下:
首先,public、private不存在这个问题。

子类姑且叫做CC(ChildClass),可以调用它所继承到的父类protected的方法暂称PM(ProtectedMethod)(不管父类该方法是继承还是实现接口来或本身定义的),前提是在他自身类中。

class CC {
method {
this.PM(); //来自父类的PM()方法
}
}

问题是在另一个类AC(AnotherClass)中不管是否具有相同父类,在里面通过实例化CC,使CC调用其继承自父类的PM,即:new CC().CM()是不可见的。

class AC {
mthod {
new CC().CM(); //complie error!!!
}
}

但令人迷惑的是如果CC重写了父类的方法PM,再在AC中调用则编译OK!

class CC {
override PM(); //重写了该方法

method {
this.PM(); //来自父类的PM()方法
}
}

class AC {
mthod {
new CC().CM(); //complie OK!!!
}
}

所以得出结论:一个类CC可以在自身里面调用父类的protected方法则可以访问。
如果在另一个类AC里面使用CC调用CC父类的方法是受到限制无法调用,但调用CC自身的protected(它重写父类protected方法或是自定义)则可以访问。

甜柠檬 2016-11-03 05:32:04

clone()方法是protected的,只有相同package可以访问
CopyObject继承重写clone()方法,调用时他们在同一个package,就不会有问题了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文