- 浏览: 899459 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
小宇宙_WZY:
膜拜一下大神,解决了我一个大问题,非常感谢 orz
【解惑】深入jar包:从jar包中读取资源文件 -
JKL852qaz:
感谢,遇到相同的问题!
【解惑】深入jar包:从jar包中读取资源文件 -
lgh1992314:
为什么java中调用final方法是用invokevirtua ...
【解惑】Java动态绑定机制的内幕 -
鲁曼1991:
说的都有道理,protected只能被同一级包的类所调用
【解惑】真正理解了protected的作用范围 -
鲁曼1991:
...
【总结】String in Java
转载: 《无聊:正确的理解this 和 super 》
原创作者: ZangXT from CSDN bolg
this和super是Java的两个关键字。
先明确一个问题,有人错误的认为它们是对象里的“属性”,这只能怪老师没有讲清楚计算机的本质了。因为计算机的处理器只能用指令去处理数据,像C语言之类的容易理解,就是一个个的方法调用,对数据进行处理。那面向对象语言,确实是用对象调用方法啊,怎么回事?
好办,编译器耍个花样,将对象当做方法的参数就是了。比如
class Test{
public void test(){}
}
Test t = new Test();
t.test();
计算机怎么处理呢?
假设我们把以上代码映射到面向过程的语言,大体是这个样子的:
void Test::test(final Test this){
}
当使用t.test();时,计算机实际处理为:
Test::test(t);//看到了吗?在方法中,this相当于形式参数,而调用方法的对象是实际参数。
也就是说this是实例方法中的第一个参数。对于static的方法,因为没有这个参数,所以就不能使用this了。
this和super的基本功能这里不想探讨,只想说明一下它们在本质上的差别。
有提法分别称之为this引用和super引用,为了表达的方便,这么说也无可厚非。但是从本质上来说,super并非一个引用,仅仅是一个起到指示作用的关键字而已,这与this在本质上是不同的。很简单的两行代码就说明问题了:
class Main { public void test() { System.out.println(this); System.out.println(super); } }
编译报错,super后面缺少.。也就说,至少在Java语言看来,super并不是一个合法的引用,而显然this是可以的。
为了表达的方便,我们仍然称super为"super引用"。这种意义下,super引用和this引用有什么差别吗?差别当然有,最重要的是,类型不 同,super的类型为父类类型引用,而this为当前类类型的引用。相同点呢?那就是这两个都是指向“当前对象”。不是说“父类对象”吗?啥,哪来的“ 父类对象”这个概念啊?
言多必失,还是看代码吧。
class Base { int i = 5; public void test() { System.out.println("In Base:" + this.i); } } public class Test extends Base { int i = 55; public void test() { //System.out.println(super); 竟然编译都不让通过 System.out.println(this); //正确,调用toString()方法 System.out.println(super.i); System.out.println(this.i); super.test(); } public static void main(String[] args) { new Test().test(); } }
看出什么了?没有。没有就对了,反汇编。
public void test(); Code: 0: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 3: aload_0 4: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V 7: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 10: aload_0 11: getfield #5; //Field Base.i:I 14: invokevirtual #6; //Method java/io/PrintStream.println:(I)V 17: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 20: aload_0 21: getfield #2; //Field i:I 24: invokevirtual #6; //Method java/io/PrintStream.println:(I)V 27: aload_0 28: invokespecial #7; //Method Base.test:()V 31: return public static void main(java.lang.String[]); Code: 0: new #8; //class Test 3: dup 4: invokespecial #9; //Method "<init>":()V 7: invokevirtual #10; //Method test:()V 10: return
注意那几个aload_0, 这可是获取this啊(前面交代了,this是实例方法的第一个参数,第一个参数当然位置是0了)!那访问this.i和super.i的差别在什么地方呢?在这个i上。
10: aload_0
11: getfield #5; //Field Base.i:I
这是获取Base定义的i
20: aload_0
21: getfield #2; //Field i:I
这是获取Test中定义的i
简单的说,Base.i和i就是当前对象中两个名字不同的字段。
有人要质疑了:瞎掰吧!如果super和this是同一个对象的引用,那super调用方法的时候不又多态了 ?这的确是个问题。不过Java的设计者考虑 到这个问题了,在jvm中提供了不同的调用方法的指令,分别是invokevirtual、invokespecial、 invokeinterface、invokedynamic等 。通过super调用实例方法时,用的就是invokespecial 指令。当 然,java的设计者们也不是一开始就考虑这么多的,invokespecial这个指令就是后来才加上的。事后诸葛亮?呵呵。
再看一下上面的反编译代码:
27: aload_0
28: invokespecial #7; //Method Base.test:()V
//用invokespecial指令避免此时发生多态调用
而多态方法调用时用什么指令呢?
看main方法是如何调用test方法的吧:public static void main(java.lang.String[]);
7: invokevirtual #10; //Method test:()V
为什么叫virtual呢?C++里有个叫做虚函数的东西,难道……
其实我们可以形象的说明一下,假设有两个变量_super和_this。
Test _this = new Test();
Super _super = _this;
这样就能更清晰的区分this和super了吧!
评论
发表评论
-
NIO
2010-08-05 10:36 0在JDK1.4以前,I/O输入输出处理,我们把它称为旧 ... -
【总结】Java线程同步机制深刻阐述
2010-05-16 10:21 6028全文转载:http://www.iteye ... -
【JDK优化】java.util.Arrays的排序研究
2010-05-12 21:06 9217作者题记:JDK中有很多算法具有优化的闪光点,值得好好研究。 ... -
【JDK优化】 Integer 自动打包机制的优化
2010-03-12 19:14 4224我们首先来看一段代码: Integer i=100; In ... -
【总结】Java与字符编码问题详谈
2009-12-30 09:11 9448一、字符集和字符编码方式 计算机只懂得0/1两种信号 ... -
【解惑】 正确理解线程等待和释放(wait/notify)
2009-12-29 13:40 19798对于初学者来说,下面这个例子是一个非常常见的错误。 /** ... -
【解惑】JVM如何理解Java泛型类
2009-12-16 11:08 12413//泛型代码 public class Pair<T& ... -
【解惑】真正理解了protected的作用范围
2009-11-21 18:00 5099一提到访问控 ... -
【总结】String in Java
2009-11-21 17:52 11000作者:每次上网冲杯Java时,都能看到关于String无休无止 ... -
【解惑】真正理解了protected的作用范围
2009-11-16 17:11 585一提到访问控制符protected,即使是初学者 ... -
总结Java标准类库中类型相互转化的方法
2009-11-09 21:57 210组一: ☆ String → byte[ ... -
方法没覆盖住带来的烦恼
2009-11-05 09:18 100Object类是所有类的祖宗,它的equals方法比较的 ... -
【解惑】数组向上转型的陷阱
2009-11-03 11:44 1894问题提出: 有两个类Manager和Em ... -
【总结】java命令解析以及编译器,虚拟机如何定位类
2009-11-01 16:25 5846学Java有些日子了,一直都使用IDE来写程序。这 ... -
【解惑】剖析float型的内存存储和精度丢失问题
2009-10-26 15:10 16134问题提出:12.0f-11.9f=0.10 ... -
【解惑】领略内部类的“内部”
2009-10-19 15:38 3604内部类有两种情况: (1) 在类中定义一个类(私有内部类 ... -
【解惑】深入jar包:从jar包中读取资源文件
2009-10-08 21:13 66025我们常常在代码中读取一些资源文件(比如图片,音乐,文 ... -
【解惑】理解java枚举类型
2009-09-26 09:37 3449枚举类型是JDK5.0的新特征。Sun引进了一个全新的关键字e ... -
编写自己的equals方法
2009-09-20 14:18 129在我的《令人头疼的"相等"关 ... -
【解惑】Java类型间的转型
2009-09-11 16:03 5690★ 基本数据类型间的转换 1、Java要做到平台无关 ...
相关推荐
理解它们的区别对于正确使用变量至关重要。 - **控制流**:包括if条件语句、for、while循环以及switch语句,这些都是编写逻辑的核心部分。 - **方法**:Java中的函数,用于封装可重用的代码。 2. **面向对象编程*...
4. **继承**:理解单一继承的概念,以及如何通过extends关键字来实现类之间的继承关系,同时掌握super关键字的使用。 5. **多态**:深入理解多态性,包括接口和抽象类,以及方法的重载和覆盖。 6. **异常处理**:...
4. **异常处理**:Java的异常处理机制通过`try-catch-finally`块实现,理解如何正确地捕获和处理异常是编写健壮代码的关键。 5. **集合框架**:ArrayList与LinkedList、HashMap与TreeMap等都是常见的集合类型,它们...
在第一篇“C语言编程中的对与错”中,作者通过分析编程中出现的典型错误,结合对比正确与错误的代码实例,加深读者对C语言编程基础知识的理解和掌握。例如,在第1章,作者列举了初学者在学习C语言时容易犯的错误,...
"java解惑"这个主题旨在帮助初学者理解和解决在学习Java过程中遇到的问题,通过实例来深入浅出地讲解Java的基础知识,同时也强调了实用技巧和注意事项。 "Java解惑"的资料可能包含了两部分:`.chm`和`.pdf`格式的...
在Java编程中,开发者经常会遇到各种误区和混淆之处,这些问题可能涉及语言特性、算法逻辑、性能优化等多方面。...总体而言,理解并正确使用Java的基本操作符和数据类型是每一个Java开发者应当掌握的关键技能。
在这个过程中,我们不仅要理解SQL的基本语法,还要掌握如何有效地查询、更新和管理数据。 首先,让我们从SQL的基础开始。SQL分为四大主要部分:数据查询语言(DQL)、数据操纵语言(DML)、数据定义语言(DDL)和...
《IT学生解惑真经》是一本专门为在IT领域学习和探索的学生们量身打造的知识宝典。这本书的目的是帮助那些在信息技术世界中迷失方向、渴望深入理解和掌握核心技术的学子们,提供一套全面且实用的学习指南。书中的内容...
书中会讲解如何正确使用try-catch-finally语句,以及如何设计和使用自定义异常。 3. **多线程编程**:Java提供了丰富的多线程支持。读者将学习到线程同步、并发工具类的使用,以及如何避免常见的并发问题。 4. **...
《JAVA解惑》这本书主要针对Java编程中遇到的各种常见问题和困惑进行了解答,旨在帮助开发者深入理解Java语言,提高编程技巧。以下是一些关键的知识点解析: 1. **异常处理**:Java中的异常处理是通过try-catch-...
java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑
《Java解惑》这篇博客文章及其配套的PDF文件,为我们提供了深入理解Java编程语言中常见问题和困惑的机会。本文将围绕“源码”和“工具”这两个关键标签,详细探讨Java编程中的若干重要知识点。 首先,Java源码是...
由于提供的文件内容主要是关于版权声明和免责申明,而不是关于C语言的具体编程知识或解惑内容,所以无法从这部分内容中提取出技术知识点。然而,根据标题和描述提供的信息,我们可以猜测这份文件可能是包含了一系列...
《Java解惑》是一本专为Java初学者和进阶者设计的指南,旨在帮助读者解决在学习和实践中遇到的各种问题。这本书深入浅出地解析了Java编程中的常见困惑,涵盖了语言基础、类库应用、多线程、网络编程、异常处理、内存...
3. **运算符和表达式**:C语言支持多种运算符,如算术运算符、比较运算符、逻辑运算符等,理解运算符优先级和结合性对于正确计算表达式非常重要。 4. **流程控制**:包括条件语句(if-else)、循环(for、while、do...
《C语言解惑》这本书是为了解决C语言学习者在编程过程中遇到的困惑而编写的,它通过一系列精心设计的编程谜题帮助读者深入理解C语言的核心概念和机制。这个压缩包文件包含了书中所有谜题的源代码,是学习和实践C语言...
《SQL解惑 第二版(中文)》是一本专门针对SQL语言疑难点进行解析的书籍,旨在帮助读者在实践中理解和掌握SQL的各种特性和技巧。这本书以其独特的案例解析方式,为学习SQL的人提供了一种生动、易懂的学习路径,避免...
《IT解惑》是一部综合性的资源集合,包含了《IT学生解惑真经》、《程序员羊皮卷》和《高质量C编程指南》三部分,旨在为计算机科学与技术的学习者和未来的职业程序员提供全面的指导和建议。这些文档分别关注了IT学生...
Java编程语言是世界上最流行的开发平台之一,广泛应用于企业级应用、...通过深入学习和理解这些Java知识点,并结合"Java解惑.pdf"文档中的实例和解决方案,开发者可以更好地解决实际开发中遇到的问题,提升编程技能。