`
yeshaoting
  • 浏览: 686092 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

上转型对象 - 平时没有注意的地方

    博客分类:
  • J2SE
阅读更多

 

多态性三种表现形式:

1. 类多态(通过继承实现)

2. 方法多态(方法重写,方法重载: 通过参数列表个数,类型不同来区分)

3. 动态连接(定义接口,然后声明上转型对象来实现)

上转型对象是将子类的对象赋值给父类的引用,形如: SuperClass sup = new SubClass();

是类多态性的一种表现形式(动态连接).

 

上转型对象不能使用子类新增成员(包括成员变量,成员方法),只能使用子类重写父类的方法,被子类隐藏的父类变量;子类未重写的父类方法,未被隐藏的父类成员变量.

 

我的误区:原来一直认为上转型对象无论是成员变量,还是成员方法都是优先访问子类的.如果子类覆盖了父类的成员变量,则上转型对象一定是访问子类覆盖父类的成员变量(子类中的成员变量),而不是访问父类中的成员变量.

 

因为JavaBean的广泛应用,平时在做Java程序的时候,因为一个读写权限的问题,常常不会对变量直接操作,而是通过成员变量的get,set方法间接操作成员变量.所以很自然错误地理解上转型对象操作变量与调用方法是类似的.

 

举例:   

 

/*
@author jarg
@TODO 上转型对象测试
*/
class SuperClass
{
	String str = "super";
	void display()
	{
		System.out.println("super class: " + this.toString());
	}
}

class SubClass extends SuperClass
{
	String str = "sub";
	void display()
	{
		System.out.println("sub class: " + this.toString());
	}
}

public class Client
{
	public static void main(String[] args)
	{
		SuperClass sup = new SubClass();
		System.out.println("sup.str=" + sup.str);
		sup.display();
	}
}

 

如上代码中,sup.str访问的是父类的变量,输出sup.str=super;而sup.display()输出subclass: SubClass@1fb8ee3.

可见,不管子类有没有覆盖父类的成员变量,SuperClass的引用都是访问父类的成员变量str=super.而被调用的display()方法显然是子类中的方法.

 

个人认为这跟数据在存储方法的差别导致了这种现象,由于本人水平有限,分析暂时到此.

 

分析不对的地方,大家给指正,谢谢.

分享到:
评论
30 楼 yeshaoting 2011-01-19  
skyuck 写道
yeshaoting 写道
shijie_262 写道
曾经听过这么一句话
通过引用取属性,不看对象看引用
通过引用调方法,不看引用看对象
可见多态性是表现在 方法上的

嗯...你说的是对的.

但为啥多态性只表现在方法上?
难道多态性表现在属性上没有意义?



比如说人这个类有名字这个属性
这是个公用的属性,根本没有必要去覆盖整个属性

子类已经有了父类的field了,子类如果需要要直接可以操作父类的field,而没有必要通过覆盖父类的属性方式。

所以说多态性表现在属性上没有意义

况且属性表现在类上多使用private的。


笨.这段话我还得再理解理解.
这必要性还没怎么想明白.
29 楼 yeshaoting 2011-01-19  
skyuck 写道
yeshaoting 写道
ray_linn 写道
本来儿子就可以重写父亲的field,根本不用再取一个同名的field...

名字是相同,但是其值(内容)不一样嘛.
就像方法重写,名字不也相同嘛~
本人愚钝,感觉没回答到点子上.



在实际开发中一般不会出现这种情况,因为一般情况下所有的field的访问域都设置成private的,因此不能直接访问他们,而是通过调用方法去访问

嗯...也对.实际开发中确实是用的javabean,然后将field权限设置成private,再有对应的set,get方法访问field.
28 楼 skyuck 2011-01-18  
yeshaoting 写道
shijie_262 写道
曾经听过这么一句话
通过引用取属性,不看对象看引用
通过引用调方法,不看引用看对象
可见多态性是表现在 方法上的

嗯...你说的是对的.

但为啥多态性只表现在方法上?
难道多态性表现在属性上没有意义?



比如说人这个类有名字这个属性
这是个公用的属性,根本没有必要去覆盖整个属性

子类已经有了父类的field了,子类如果需要要直接可以操作父类的field,而没有必要通过覆盖父类的属性方式。

所以说多态性表现在属性上没有意义

况且属性表现在类上多使用private的。

27 楼 yeshaoting 2011-01-18  
shijie_262 写道
曾经听过这么一句话
通过引用取属性,不看对象看引用
通过引用调方法,不看引用看对象
可见多态性是表现在 方法上的

嗯...你说的是对的.

但为啥多态性只表现在方法上?
难道多态性表现在属性上没有意义?
26 楼 yeshaoting 2011-01-18  
haigui.chen 写道
yeshaoting 写道
haigui.chen 写道
重写(override):父类中的实例方法被其子类重新实现。既然是实例方法,那就是非 static 修饰的了,否则就是 static 静态方法了,那叫做类方法。在我看来,正是重写这一机制的存在,才为多态机制提供了基础。或许 implements (实现)一个 interface (接口)中所声明的方法也能成为重写,因为 interface 的一部分存在原因也是为了多态。


隐藏(hide):子类的某个字段、静态方法、成员内部类与其父类的具有相同名字(对于静态方法还需要相同的参数列表),此时父类对应的字段、静态方法、成员内部类就被隐藏了


嗯.学习了~
重写说得蛮好,隐藏貌似有点空洞.



其实,这些概念,如果能看看bytecode是非常清楚的。
对于override基本上用invokevirtual 指令,这个名字就很形象...
而对于static的方法,用的是invokestatic,而且static方法最好通过class 名字调用,就很清楚了,对象引用时什么类型,就是调用的该类型的方法...
btw,对于interface,用的invokeinterface。

对于LZ提到的访问变量,用的getfield,对于field,记住,它不能被重写.

Fields cannot be overriden


啰嗦这么多,希望能稍微解释清楚点...

嗯.不啰嗦,说得挺好的.
虽然好多我还听不太懂.
倒是给我引入了一些新的知识,一些虚拟机方面底层的知识.
现在欠缺的知识还是蛮多的,过年回家好好学习.
以后的学习中会注意了解的.
再次感谢~
25 楼 haigui.chen 2011-01-18  
yeshaoting 写道
haigui.chen 写道
重写(override):父类中的实例方法被其子类重新实现。既然是实例方法,那就是非 static 修饰的了,否则就是 static 静态方法了,那叫做类方法。在我看来,正是重写这一机制的存在,才为多态机制提供了基础。或许 implements (实现)一个 interface (接口)中所声明的方法也能成为重写,因为 interface 的一部分存在原因也是为了多态。


隐藏(hide):子类的某个字段、静态方法、成员内部类与其父类的具有相同名字(对于静态方法还需要相同的参数列表),此时父类对应的字段、静态方法、成员内部类就被隐藏了


嗯.学习了~
重写说得蛮好,隐藏貌似有点空洞.



其实,这些概念,如果能看看bytecode是非常清楚的。
对于override基本上用invokevirtual 指令,这个名字就很形象...
而对于static的方法,用的是invokestatic,而且static方法最好通过class 名字调用,就很清楚了,对象引用时什么类型,就是调用的该类型的方法...
btw,对于interface,用的invokeinterface。

对于LZ提到的访问变量,用的getfield,对于field,记住,它不能被重写.

Fields cannot be overriden


啰嗦这么多,希望能稍微解释清楚点...
24 楼 yeshaoting 2011-01-18  
haigui.chen 写道
重写(override):父类中的实例方法被其子类重新实现。既然是实例方法,那就是非 static 修饰的了,否则就是 static 静态方法了,那叫做类方法。在我看来,正是重写这一机制的存在,才为多态机制提供了基础。或许 implements (实现)一个 interface (接口)中所声明的方法也能成为重写,因为 interface 的一部分存在原因也是为了多态。


隐藏(hide):子类的某个字段、静态方法、成员内部类与其父类的具有相同名字(对于静态方法还需要相同的参数列表),此时父类对应的字段、静态方法、成员内部类就被隐藏了


嗯.学习了~
重写说得蛮好,隐藏貌似有点空洞.
23 楼 skyuck 2011-01-18  
yeshaoting 写道
ray_linn 写道
本来儿子就可以重写父亲的field,根本不用再取一个同名的field...

名字是相同,但是其值(内容)不一样嘛.
就像方法重写,名字不也相同嘛~
本人愚钝,感觉没回答到点子上.



在实际开发中一般不会出现这种情况,因为一般情况下所有的field的访问域都设置成private的,因此不能直接访问他们,而是通过调用方法去访问
22 楼 yeshaoting 2011-01-18  
ray_linn 写道
本来儿子就可以重写父亲的field,根本不用再取一个同名的field...

名字是相同,但是其值(内容)不一样嘛.
就像方法重写,名字不也相同嘛~
本人愚钝,感觉没回答到点子上.
21 楼 yeshaoting 2011-01-18  
skyuck 写道
java编程思想  多态那一章节有讲

另外我的博客第一篇也是谈这个的

晚上会寝室会看会java编程思想,我比较笨,看得慢.
过年回家好好学下...真的很欠缺.

一会去你博客学习学习.
20 楼 shijie_262 2011-01-18  
曾经听过这么一句话
通过引用取属性,不看对象看引用
通过引用调方法,不看引用看对象
可见多态性是表现在 方法上的
19 楼 skyuck 2011-01-18  
java编程思想  多态那一章节有讲

另外我的博客第一篇也是谈这个的
18 楼 haigui.chen 2011-01-18  
重写(override):父类中的实例方法被其子类重新实现。既然是实例方法,那就是非 static 修饰的了,否则就是 static 静态方法了,那叫做类方法。在我看来,正是重写这一机制的存在,才为多态机制提供了基础。或许 implements (实现)一个 interface (接口)中所声明的方法也能成为重写,因为 interface 的一部分存在原因也是为了多态。


隐藏(hide):子类的某个字段、静态方法、成员内部类与其父类的具有相同名字(对于静态方法还需要相同的参数列表),此时父类对应的字段、静态方法、成员内部类就被隐藏了
17 楼 ray_linn 2011-01-18  
本来儿子就可以重写父亲的field,根本不用再取一个同名的field...
16 楼 yeshaoting 2011-01-17  
qz小峰 写道
getfield和invokevirtual这两个指令中有详细介绍.
http://www.brics.dk/~mis/dOvs/jvmspec/ref-Java.html


哇哦,英文的~~
现在在看英文的论文,有点排斥英文的东西
15 楼 yeshaoting 2011-01-17  
snake1987 写道
突然发现自己也没注意过这个问题~
学习了

哈哈...现在用JavaBean用得太多了.
很少对变量直接操作了.
14 楼 qz小峰 2011-01-17  
getfield和invokevirtual这两个指令中有详细介绍.
http://www.brics.dk/~mis/dOvs/jvmspec/ref-Java.html

13 楼 kingkan 2011-01-17  
yeshaoting 写道
silentlakeside 写道
属性,私有方法、静态方法、final方法都是静态绑定的,即编译期确定的。
其他方法是动态绑定的,即虚拟机运行时确定。
后者才可能出现override的情况。

是目前最好,最清楚的解释了.


+1
12 楼 snake1987 2011-01-17  
突然发现自己也没注意过这个问题~
学习了
11 楼 jlpsyx123 2011-01-17  
freish 写道
yeshaoting 写道
weilingfeng98 写道
java的机制

谢谢你的回复...
嗯...我知道是java的机制.
我想知道这个机制的过程,具体是怎么做...
想多了解一点.



《深入java虚拟机》,不多说

还不多说。。有什么啊。。。。。。哎

相关推荐

Global site tag (gtag.js) - Google Analytics