为什么子类能够间接调用父类的私有方法

fatsunwood 2014-11-18 10:23:44
子类的对象是不能直接调用父类的私有方法,但是却可以间接调用,求大家解答!代码如下
class Father{

public Father(){
System.out.println("Father");
}
private void hello(){
System.out.println("hello");
}

public void sayHello(){
System.out.println(this instanceof Son);
this.hello();
}
}
public class Son extends Father{

public static void main(String[] args) {
Son s = new Son();
s.sayHello();
}

}
...全文
1407 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
枫0子K 2014-11-25
  • 打赏
  • 举报
回复
public void sayHello(){ System.out.println(this instanceof Son); this.hello(); } } 因为Son跟Father存在继承关系,所以用instanceof来判断的话,判断结果都是true。(查instanceof跟类继承相关的资料) 私有方法外部不能访问是指你不能这么访问:son.hello(); 对于楼主的疑问好像更偏重于是,为什么能借助sayHello这个方法来访问到Father类中的私有hello方法。 关键点在于这个this代表着什么,像上面所说的,跟instnaceof判断出来的结果没关系。要看编译器在这里把this当成什么。 我对于这个this的理解是这样:直属于哪个类,this就代表这个类的实例。 也就是说,sayHello中的this,其实是假借Father之手去调用了hello方法,所以当然可以访问。 扩展: 你可以试试在一个按钮点击事件里面去使用this,这个时候this只能访问到OnClickListener中的方法跟属性,而不能访问注册按钮事件的类的方法跟属性,这时候的this即代表OnClickListener的实例,道理是一样的。
xiejin90314 2014-11-25
  • 打赏
  • 举报
回复 2
你爸的钱是你的钱吗?很明显不是。。 你找你爸要钱,你爸给你钱了,现在钱就是你的了。
fatsunwood 2014-11-20
  • 打赏
  • 举报
回复
引用 23 楼 yanxing2012 的回复:
[quote=引用 16 楼 fatsunwood 的回复:] [quote=引用 15 楼 yanxing2012 的回复:] [quote=引用 14 楼 abcdefghiijklmnopqrs 的回复:] [quote=引用 13 楼 cgy_workman 的回复:] [quote=引用 4 楼 cgy_workman 的回复:] 额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖[/quote] sayHello()方法中的System.out.println(this instanceof Son);显示TRUE,应该为子类对象,那下一句的this.hello();子类的对象调用父类私有方法怎么解释?[/quote] 正如你所说子类的对象是不能直接调用父类的私有方法,但是却可以间接调用,这里是间接调用,子类和父类指向同一地址空间。[/quote] 为什么间接就可以了,进入到sayHello方法后,什么发生了改变,导致子类对象可以访问父类私有方法[/quote] 你直接用子类对象调用父类私有方法,会提示这个方法不可见,这是封装特性,对外不可见。进入sayHello方法,那是父类的方法,这时sayHello没有被重写,所以调用的是父类的方法,在父类方法中调用父类自己的方法(私有方法也可调用),即使this是子类对象,这时可见了,或者说找到地址了[/quote] 可不可以这样理解,父类的私有方法对子类不可访问是在编译的时候限制的,但是执行的时候,是不会限制的
kainever 2014-11-20
  • 打赏
  • 举报
回复
这是不是 跟get / set 是一个意思了...........
yanxing2012 2014-11-19
  • 打赏
  • 举报
回复
引用 16 楼 fatsunwood 的回复:
[quote=引用 15 楼 yanxing2012 的回复:] [quote=引用 14 楼 abcdefghiijklmnopqrs 的回复:] [quote=引用 13 楼 cgy_workman 的回复:] [quote=引用 4 楼 cgy_workman 的回复:] 额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖[/quote] sayHello()方法中的System.out.println(this instanceof Son);显示TRUE,应该为子类对象,那下一句的this.hello();子类的对象调用父类私有方法怎么解释?[/quote] 正如你所说子类的对象是不能直接调用父类的私有方法,但是却可以间接调用,这里是间接调用,子类和父类指向同一地址空间。[/quote] 为什么间接就可以了,进入到sayHello方法后,什么发生了改变,导致子类对象可以访问父类私有方法[/quote] 你直接用子类对象调用父类私有方法,会提示这个方法不可见,这是封装特性,对外不可见。进入sayHello方法,那是父类的方法,这时sayHello没有被重写,所以调用的是父类的方法,在父类方法中调用父类自己的方法(私有方法也可调用),即使this是子类对象,这时可见了,或者说找到地址了
_reason 2014-11-19
  • 打赏
  • 举报
回复
使用private修饰方法相当于标记此方法不应是程序员关注的重点,它是为public修饰的方法服务的,jdk源码里有大量private修饰的方法,它们会在public修饰的方法中得到调用。 子类通过继承得到公共方法,而操作是在父类的方法中完成的。子类只负责调用父类的那个方法,除非你覆盖它。 这样并没有破坏封装,因为子类仍然不能调用父类的私有方法。
_reason 2014-11-19
  • 打赏
  • 举报
回复
引用 12 楼 u010005508 的回复:
1)instanceof说明:instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个操作数通常是一个类(也可以是接口,可以把接口理解成一种特殊的类),它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,则返回true,否则返回false。在使用instanceof运算符要注意:instanceof运算符前面操作数的编译时类型要么与后面的类相同,要么是后面类的父类,否则会引起编译错误(摘自 李刚【疯狂java讲义】) 2)关于楼主的问题,我这样理解:当子类继承父类时,子类会继承父类所有的方法(不管这个方法的访问权限是private、protected、public的);只不过在子类自己定义的方法中无法直接去访问继承而来的private方法罢了,但是可以通过继承而来的public及protected方法来间接访问继承而来的private方法。 即可以简单的将子类的方法分为两个版本,一是继承自父类的方法(简称继承版),二是自己定义的方法(简称自定版义版);但是不管是继承版的还是自定义版的方法,它们都是属于这个子类的,所以当子类实例化一个对象去调用这些方法时,这些方法中的this变量肯定指向这个对象本身(只不过访问继承版的private方法时,需要绕一点弯路) 将楼主代码简单修改后验证了上面说法,如下:
class Father {
	public Father() {
		System.out.println("Father");
	}
	
	private void hello(Son son) {
		System.out.println("hello");
		System.out.println(this==son);//输出true,说明this和son引用的是同一个对象
	}

	public void sayHello(Son son) {
		System.out.println(this instanceof Son);
		this.hello(son);
	}
}

public class Son extends Father {
	
	public static void main(String[] args) {
		Son s = new Son();
		s.sayHello(s);
	}
}
楼主,私有属性和方法在子类中确实存在,但这是由于创建对象的流程决定的,而非继承得到,它们在子类当中已经无法继续使用了。(官方对此有很明确的说明)
wyc_ 2014-11-19
  • 打赏
  • 举报
回复
都没说到点子上,System.out.println(this instanceof Son);输出真怎么解释?
_reason 2014-11-19
  • 打赏
  • 举报
回复
引用 9 楼 cumtwyc 的回复:
都没说到点子上,System.out.println(this instanceof Son);输出真怎么解释?
子类通过继承得到了父类的sayHello方法,因此子类调用的是自己的sayHello()方法,那么这个this就是调用类本身 在sayHello()中添加这句System.out.println(this.getClass().getName());就会得到很明确的结果
后飞的笨鸟儿 2014-11-19
  • 打赏
  • 举报
回复
引用 14 楼 abcdefghiijklmnopqrs 的回复:
[quote=引用 13 楼 cgy_workman 的回复:] [quote=引用 4 楼 cgy_workman 的回复:] 额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖[/quote] sayHello()方法中的System.out.println(this instanceof Son);显示TRUE,应该为子类对象,那下一句的this.hello();子类的对象调用父类私有方法怎么解释?[/quote] System.out.println(this instanceof Father); 也会显示true的。。。。内存解析。。。
后飞的笨鸟儿 2014-11-19
  • 打赏
  • 举报
回复
引用 17 楼 cgy_workman 的回复:
[quote=引用 16 楼 fatsunwood 的回复:] [quote=引用 15 楼 yanxing2012 的回复:] [quote=引用 14 楼 abcdefghiijklmnopqrs 的回复:] [quote=引用 13 楼 cgy_workman 的回复:] [quote=引用 4 楼 cgy_workman 的回复:] 额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖[/quote] sayHello()方法中的System.out.println(this instanceof Son);显示TRUE,应该为子类对象,那下一句的this.hello();子类的对象调用父类私有方法怎么解释?[/quote] 正如你所说子类的对象是不能直接调用父类的私有方法,但是却可以间接调用,这里是间接调用,子类和父类指向同一地址空间。[/quote] 为什么间接就可以了,进入到sayHello方法后,什么发生了改变,导致子类对象可以访问父类私有方法[/quote] 已经在上面提到了,你在加一句System.out.println(this instanceof Son);答案也是true。 另外,没什么变化,看图,this引用是从父类的对象指向自己的方法。[/quote] 额,是加一句System.out.println(this instanceof Father);答案也是true
后飞的笨鸟儿 2014-11-19
  • 打赏
  • 举报
回复
引用 16 楼 fatsunwood 的回复:
[quote=引用 15 楼 yanxing2012 的回复:] [quote=引用 14 楼 abcdefghiijklmnopqrs 的回复:] [quote=引用 13 楼 cgy_workman 的回复:] [quote=引用 4 楼 cgy_workman 的回复:] 额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖[/quote] sayHello()方法中的System.out.println(this instanceof Son);显示TRUE,应该为子类对象,那下一句的this.hello();子类的对象调用父类私有方法怎么解释?[/quote] 正如你所说子类的对象是不能直接调用父类的私有方法,但是却可以间接调用,这里是间接调用,子类和父类指向同一地址空间。[/quote] 为什么间接就可以了,进入到sayHello方法后,什么发生了改变,导致子类对象可以访问父类私有方法[/quote] 已经在上面提到了,你在加一句System.out.println(this instanceof Son);答案也是true。 另外,没什么变化,看图,this引用是从父类的对象指向自己的方法。
fengzhw 2014-11-19
  • 打赏
  • 举报
回复
引用 6 楼 xiangnan129 的回复:
我的理解是这样的,当你使用s.sayHello();这句的时候,应该是会有一个父类的隐藏对象, 也就是说表面上是子类对象s调用了sayHello方法,应该是还是s->father->sayHello; 所以当this.hello();时也就类似了this->father->hello。 全凭个人理解见解,等待高手的详细解答。
支持!子类通过继承扩展了父类以后,也拥有了和父类完全相同的能力,这里完全是父类实例自己完成的调用。 从封装的角度来讲,撇开一切private的东西,才能更准确把握类之间的职责:谁负责干什么。
wyc_ 2014-11-19
  • 打赏
  • 举报
回复
顶一下,求高手解答
fatsunwood 2014-11-19
  • 打赏
  • 举报
回复
引用 15 楼 yanxing2012 的回复:
[quote=引用 14 楼 abcdefghiijklmnopqrs 的回复:] [quote=引用 13 楼 cgy_workman 的回复:] [quote=引用 4 楼 cgy_workman 的回复:] 额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖[/quote] sayHello()方法中的System.out.println(this instanceof Son);显示TRUE,应该为子类对象,那下一句的this.hello();子类的对象调用父类私有方法怎么解释?[/quote] 正如你所说子类的对象是不能直接调用父类的私有方法,但是却可以间接调用,这里是间接调用,子类和父类指向同一地址空间。[/quote] 为什么间接就可以了,进入到sayHello方法后,什么发生了改变,导致子类对象可以访问父类私有方法
yanxing2012 2014-11-19
  • 打赏
  • 举报
回复
引用 14 楼 abcdefghiijklmnopqrs 的回复:
[quote=引用 13 楼 cgy_workman 的回复:] [quote=引用 4 楼 cgy_workman 的回复:] 额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖[/quote] sayHello()方法中的System.out.println(this instanceof Son);显示TRUE,应该为子类对象,那下一句的this.hello();子类的对象调用父类私有方法怎么解释?[/quote] 正如你所说子类的对象是不能直接调用父类的私有方法,但是却可以间接调用,这里是间接调用,子类和父类指向同一地址空间。
  • 打赏
  • 举报
回复
引用 13 楼 cgy_workman 的回复:
[quote=引用 4 楼 cgy_workman 的回复:] 额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖[/quote] sayHello()方法中的System.out.println(this instanceof Son);显示TRUE,应该为子类对象,那下一句的this.hello();子类的对象调用父类私有方法怎么解释?
后飞的笨鸟儿 2014-11-19
  • 打赏
  • 举报
回复
引用 4 楼 cgy_workman 的回复:
额,是我马虎了 重新解释下给您: 首先,子类继承父类,new 子类的过程中会调用父类构造方法,即new 父类。堆内存分配了一块空间,其中包含一个子类对象,且子类对象内包含一个父类对象。在父类定义的方法中调用this.hello(),是从父类对象自身指向其内部的hello()方法。 你可以这样做,在你的代码中,System.out.println(this instanceof Son);下面再加一行:System.out.println(this instanceof Father); 相信这样你可以看明白。来张草图:哈哈
话说。。。我这解释有问题么?求高手拍砖
highnewrain 2014-11-19
  • 打赏
  • 举报
回复
1)instanceof说明:instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个操作数通常是一个类(也可以是接口,可以把接口理解成一种特殊的类),它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,则返回true,否则返回false。在使用instanceof运算符要注意:instanceof运算符前面操作数的编译时类型要么与后面的类相同,要么是后面类的父类,否则会引起编译错误(摘自 李刚【疯狂java讲义】)

2)关于楼主的问题,我这样理解:当子类继承父类时,子类会继承父类所有的方法(不管这个方法的访问权限是private、protected、public的);只不过在子类自己定义的方法中无法直接去访问继承而来的private方法罢了,但是可以通过继承而来的public及protected方法来间接访问继承而来的private方法。
即可以简单的将子类的方法分为两个版本,一是继承自父类的方法(简称继承版),二是自己定义的方法(简称自定版义版);但是不管是继承版的还是自定义版的方法,它们都是属于这个子类的,所以当子类实例化一个对象去调用这些方法时,这些方法中的this变量肯定指向这个对象本身(只不过访问继承版的private方法时,需要绕一点弯路)

将楼主代码简单修改后验证了上面说法,如下:
class Father {
public Father() {
System.out.println("Father");
}

private void hello(Son son) {
System.out.println("hello");
System.out.println(this==son);//输出true,说明this和son引用的是同一个对象
}

public void sayHello(Son son) {
System.out.println(this instanceof Son);
this.hello(son);
}
}

public class Son extends Father {

public static void main(String[] args) {
Son s = new Son();
s.sayHello(s);
}
}

wyc_ 2014-11-19
  • 打赏
  • 举报
回复
引用 10 楼 fengzhw 的回复:
[quote=引用 9 楼 cumtwyc 的回复:] 都没说到点子上,System.out.println(this instanceof Son);输出真怎么解释?
System.out.println(this instanceof Son); System.out.println(this instanceof Father); 哪个会是假?多态就是这么玩的啊。。。[/quote] 嗯,谢谢,写了个程序测试了一下,的确是这样子。不过这个this相当于我下面程序中的f还是是呢?
class Father
{
}
class Son extends Father
{
}
public class Test{
	public static void main(String[] args)throws Exception{
		Father f = new Son();
		System.out.println(f instanceof Father);//true
		System.out.println(f instanceof Son);//true
		Son s = new Son();
		System.out.println(s instanceof Father);//true
		System.out.println(s instanceof Son);//true
	}
}
加载更多回复(7)

62,636

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧