`

[原创][2013.12.03]java多态 this 理解汇总

阅读更多

 

原帖地址:http://justt0.iteye.com/admin/blogs/1983634/edit

 

package com.p1;

public class Father {
	void test(){
		this.go();//即go();
	}
	void go(){
		System.out.println("father go");
	}
}

package com.p1;

public class Son extends Father {

	@Override
	void test() {
		// TODO Auto-generated method stub
		//指定super.test();
		super.test();
		//指定super.go();
		super.go();
	}

	@Override
	void go() {
		// TODO Auto-generated method stub
		System.out.println("son go");
	}

	public static void main(String[] args) {
		Father f = new Son();
		f.test();
	}
}

 

提到多态,首先要清楚创建子类的时候都发生了什么.(变量初始化总是在构造方法之前,我们在这里忽略它)我们知道执行new Son();后,由于继承关系,所以会先初始化父类---即会先创建一个父类对象(基对象这个对象是真实存在的,它和直接创建基类对象的区别是,前者的对象是包装在导出类的内部,后者则是外部),然后才是初始化子类--即创建子类对象,最后的结果是导出类对象(Son对象)的内部包装了一个基类对象(Father对象).

    我们再说创建对象的方式,Father f = new Son();这是将一个Son对象付给了一个Father引用,事实上f就是一个Son对象,但是这个f只能访问基类对象子类对象都有的方法,然后执行f.test();方法,因为f指向的对象其实还是一个Son对象,所以调用的test方法就是son对象的test方法.

    然后我们再说关键字this和super,有了上面的分析,我们可以将this认为是指向导出类对象,super指向的则是积累对象,有了这个思路,理解多态就容易多了.基类有两个方法,test()和go(),test调用go,在子类中我们覆盖这两个方法,父类的go()方法打印的是"father go",而子类的go()方法打印的是"son go",好了,go方法就这样,再说调用go方法的test方法,我们假设两种情况:

       情况一:子类的test方法里面调用父类的test方法,即super.test();看到这个super了吧,它指的就是基类对象,好了,这样我们直接找到基类的test方法,它调用的是go();,这个go();我们也可以写成this.go();(这个都清楚吧,两种写法一个意思),好了,this出现了,这个this指的就是子类对象,那我们直接就找子类的go()方法,所以打印的是"son go",怎么样?容易吧?

       情况二:子类的test方法里面直接调用父类的go方法,即super.go();看到super了吧,它指的是基类对象,这样我们直接找到父类的go()方法,所以打印的是"father go",即使子类有覆盖go()方法,没用.

    说到这里,有朋友可能会想到,如果子类没有覆盖父类的go方法,子类只是覆盖基类的test方法呢?  这其实又是两种情况,理解方法也很简单:

       情况一:如果子类的test方法执行的是super.test(),由于父类的test方法调用的是go()(即this.go();),这个this代指子类对象,但是子类对象并没有自己的go()方法,怎么办? 其实我们可以把它看成是一层一层的,如果子类没有go方法,那么它就会向里面找,所以就会找到父类的go()方法,所以就会打印出"father go"的结果.

       情况二:如果子类的test方法执行的是super.go(),直接找到父对象的go方法,没说的,打印的是"father go".

    可能有人又会想到,如果子类什么都没覆盖,只是继承了父类呢? 这其实又是一种情况,f.test();调用子类的test()方法,由于子类没有明确覆盖test方法,所以,向里找,在基类找到了test方法,然后test方法里调用了this.go();方法,this代指Son对象,在Son对象里又没找到明确覆盖的go()方法,所以又向里找,所以找到了基类对象的go()方法,所以打印的是father go.

 

 [2013.12.03]更新

今天看到IBM官网上的一篇文章,http://www.ibm.com/developerworks/cn/java/j-lo-polymorph/,印证了我的理解,首先,this指的就是实际的对象,不管引用对象的引用是什么,对象的类型是不变的,比如,Father f = new Son();即使引用Son对象的是Father的引用,但如果你试一下将f打印出来,然后再将f向上转型为son,然后将转型后对象打印出来,你就会发现两者打出来的结果是一致的,就是com.p1.Son@142c63f,为什么呢? 看下源码就会发现,如果system.out.println();打印一个object的话,调用的是该object的toString方法,源码是这样的:

   public String toString() {

        return getClass().getName() + "@" + Integer.toHexString(hashCode());

    }

意思是类的名字+@+对象的hashcode的16进制字符串表现形式,hashcode大家都知道,是唯一的,再看上面的结果com.p1.Son@142c63f,首先,即使是Father引用指向的他,但他还是一个Son对象,再看hashcode部分,转型前后@后面的都一样,说明,对象还是那个对象,没有产生新对象.

    接着,我们回到主题,http://www.ibm.com/developerworks/cn/java/j-lo-polymorph/,这篇文章有一幅描绘方法表的图:

 大概意思是,girl和boy都继承自object,我们拿girl来说,首先,girl复写了object的toString()方法,然后,girl又多了两个方法,eat()和speak(),对于一个girl对象来说如果调用girl的eat()方法,哪个箭头(我们把他看做指针),就会直接指向girl的eat();如果调用的是toStirng();方法,但是object有同名方法,怎么办? 答案是,指针会直接指向girl里面的toString();方法,而忽略掉object里面toStirng方法,这其实就是多态的实现,很清晰的思路,再说如果调用没有被girl复写的object方法,指针会直接指向object的方法代码,也很简单.

 

至于变量的覆盖,可以参照这篇文章,http://developer.51cto.com/art/201204/327772.htm和这篇文章http://blog.csdn.net/tryandlearn/article/details/8742367

1
1
分享到:
评论

相关推荐

    java多态练习题

    java多态、继承练习题,包含题目与答案,............................................................................................................

    java多态的理解共3页.pdf.zip

    Java多态是面向对象编程中的一个核心概念,它在Java编程中扮演着至关重要的角色。多态性(Polymorphism)一词源自希腊语,意为“多种形态”,在计算机科学中,它允许我们使用一个接口来表示多种类型的数据,从而实现...

    计算机后端-PHP视频教程. php之面向对象29 多态(选学).wmv

    计算机后端-PHP视频教程. php之面向对象29 多态(选学).wmv

    对java中多态理解

    对 Java 中多态理解 Java 中的多态是指在不同的情况下可以有不同的行为,多态是面向对象编程的一种基本特征。多态的实现是通过方法重载和方法重写来实现的。 在 Java 中,多态可以分为两种:编译时多态和运行时...

    java多态理解

    Java多态理解 java中的多态性是面向对象编程的精髓所在。多态性是指父类引用指向子类对象,例如父类Animal,子类Cat和Dog。其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类。Animal animal = ...

    C++开发基于多态的公司职工管理系统(课设源码).zip

    C++开发基于多态的公司职工管理系统(课设源码).zipC++开发基于多态的公司职工管理系统(课设源码).zipC++开发基于多态的公司职工管理系统(课设源码).zipC++开发基于多态的公司职工管理系统(课设源码).zipC++开发基于...

    .archivetemp04 - 继承和多态 作业.doc

    ### 继承与多态知识点解析 #### 一、继承的特点及应用场景 **定义与特点:** 继承是一种面向对象编程的基本特性,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。通过继承,可以...

    Python工具箱.zip - 办公自动化、多态文件搜索、高级加密

    Python工具箱.zip - 办公自动化、多态文件搜索、高级加密。Python工具箱.zip - 办公自动化、多态文件搜索、高级加密。Python工具箱.zip - 办公自动化、多态文件搜索、高级加密。Python工具箱.zip - 办公自动化、多态...

    java多态实验

    在这个“java多态实验”中,我们可以看到一系列小代码实例,这些实例旨在帮助理解和应用多态特性。下面我们将深入探讨多态的概念、实现方式以及它在实际开发中的应用。 1. 多态性定义: 多态(Polymorphism)源自...

    编程语言JAVA多态的理解.pdf

    ### 理解Java中的多态 首先,Java中的多态是通过方法重载(Overloading)和方法重写(Overriding)实现的。方法重载发生在同一个类中,而方法重写发生在子类和父类之间。 #### 方法重写(方法覆盖) 在上述代码中...

    Java多态案例及源码.rar

    Java多态是面向对象编程中的一个核心概念,它允许我们使用父类引用处理子类对象,从而实现更灵活的代码设计。在这个“Java多态案例及源码.rar”压缩包中,你将找到一系列关于Java多态的实例和源代码,非常适合教师在...

    java 多态.docx

    在Java编程语言中,多态(Polymorphism)是一种核心特性,它允许我们设计更加灵活、可扩展的代码。多态使得一个接口可以有多种不同的实现或者表现形式,...理解和熟练运用多态,对于编写高质量的Java应用程序至关重要。

    关于Java多态实例共3页.pdf.zip

    通过理解并熟练运用上述Java多态的概念,开发者可以编写出更加灵活、可扩展的代码,提升软件系统的整体质量和性能。在实际项目中,多态性常用于构建模块化的系统,使组件之间能以一种松散耦合的方式交互,实现高效的...

    深入理解Java多态.pptx.pptx

    Java多态是面向对象编程的核心特性之一,它允许我们使用一个通用的接口来处理不同类型的对象,从而实现代码的灵活性和可扩展性。在Java中,多态主要通过三种方式实现:继承、接口和方法的重写。 1. **继承与多态**...

    Java_ploymorphism.rar_ploymorphi_多态

    在这个"Java_ploymorphism.rar"压缩包中,包含的四个Java源文件——ArrayListTest.java、ObjectVarTest.java、ObjectTypeTest.java和BasicTypeTest.java,很可能是用来演示和练习Java多态性的不同应用场景。...

    java多态的总结

    Java的多态性是面向对象编程的一个核心特性,它允许我们使用一个接口来表示不同的类,使得代码更加灵活,易于维护。多态性是通过继承、接口和方法重写来...理解并熟练运用多态,能帮助开发者编写出更高质量的Java程序。

    Java多态,面向对象编程题demo.zip

    Java多态是面向对象编程中的一个核心概念,它允许我们以一种统一的方式处理不同类型的对象。在Java中,多态性主要体现在方法的重写(Override)和重载(Overload)。通过多态,我们可以编写出更加灵活、可扩展的代码...

    java23.7.12-继承抽象多态

    在Java编程语言中,继承、抽象和多态是面向...通过理解并熟练运用继承、抽象和多态,开发者可以构建出更加灵活、高效且易于扩展的Java应用程序。在实际开发中,这三个概念常常结合使用,以实现复杂的功能和业务逻辑。

    Java多态的实现机制

    Java多态的实现机制 Java 多态的实现机制是面向对象程序设计中代码重用的一个重要机制。多态性是 Java 的三大属性之一,在开发中很重要的一个环节。多态性使对象能够调用正确的方法版本,从而提高代码的重用性和...

Global site tag (gtag.js) - Google Analytics