Java中this关键字
来源:互联网 发布:新概念英语 软件 编辑:程序博客网 时间:2024/06/13 00:29
我们通常在用Java中的this关键字的时候,都知道this是代表正在调用这个类的方法的当前实例。通常情况下理解this关键字还是很容易的,但是在我初学的时候,有一个疑问却一直不能很清晰的理解,现在慢慢的理解了,就想把它记下来,也许有人和我有相同的疑问,说不定可以帮助到别人。我们还是先简单的看看通常情况下this的作用吧。比如下面的代码:
public class Leaf { private int i = 0; Leaf increment() { i++; return this; } void print() { System.out.println("i = " + i); } public static void main(String[] args) { Leaf x = new Leaf(); x.increment().increment().print(); }}
在Leaf类的main方法中,我们new了一个Leaf实例 x,然后x实例调用increment()方法。如果increment()是普通的方法或者void方法,这个地方就没有什么值得我们研究的了。特殊的是,在increment()方法中,我们return的是一个this,这个this代表的就是我们刚刚创建的x。因为x正在调用increment()方法,所以,increment()方法this就很明显代表的是Leaf的x实例了。
这看起来没有什么可讨论的,this就是代表的调用该方法的实例x。可是,假如我们把main()函数修改成下面的样子:
public static void main(String[] args) { Leaf x = new Leaf(); x.increment().increment().print(); Leaf y = new Leaf(); y.increment().increment().print();}
以上修改的代码中,我们增加创建了一个Leaf实例y,然后y也连续调用调用了两次increment()。现在问题来了,假如 x,y同时调用的increment()方法,那么this到底能代表谁呢?你可能会觉得这有什么问题,x调用increment()方法,this就代表x, y调用increment()方法,this就代表y。可问题是,当我们讲调用方法的时候,在jvm层面上是找到Leaf类中increment()方法所在的内存地址,然后在java虚拟机栈中创建栈帧,
然后在栈帧中执行方法里面的代码。现在看到了吧,也就是说,在jvm执行方法层面,没有所谓的x调用,y调用了,那么,方法中的this到底是怎么确定指向哪个实例的呢?
我们还是来看看Leaf类字节码中是怎么展示的,是不是我们漏了什么,如果我们没有把x实例或者y实例传递到方法里面去,那么,在jvm执行方法的时候,是不可能知道this具体指向哪个实例的。
到这里,我们看到在increment()方法中,编码中没有参数,但是在字节码里面却显示参数个数为1,仔细想想,结果已经很明显了:jvm在执行编译的时候,在实例方法中,会默认隐藏的传递一个参数,这个参数就是当前调用的实例本身。比如x调用,隐藏就把x传过去,y调用,就把y传过去。所以,我们的this才能在jvm执行方法层面确定到底指向的是谁。
上面的结论是我们自己推断出来的,有没有那本书对这个有详细的描述呢?《java编程思想》里面,对这块是这样描述的:
假定我们在一个方法的内部,并希望获得当前对象的句柄。由于那个句柄是由编译器“秘密”传递的,所以没有标识符可用。然而,针对这一目的有个专用的关键字:this。
在里面讲的这个编译器秘密传递的句柄,就是我们这里的这个隐藏参数。
到此为止,关于this的描述想必已经很清楚了,我们在jvm层面对它进行了理解。那么,各位有没有兴趣在看下下面的这个例子,想想这个基类B中的this代表了什么呢?
public class B { public B() { System.out.println(this.getClass().getSimpleName()); System.out.println(((A) this).a); }}public class A extends B { public int a = 100; public A() { a = 200; } public static void main(String[] args) { new A(); }}
这个例子原本是为了了解java具有继承结构的时候类是怎么完成初始化的,可是这里面的B类中的构造函数比较特殊:B类中的构造函数中的this输出的SimpleName是A。通常我们遇到的情况,B类中的this输出的SimpleName应该是B,可是这里却是A?为什么?
在上面我们讲this的过程中,其实已经涉及到这块了,在调用java方法创建栈帧的时候,jvm会秘密的传递一个当前实例。所以,当我们在执行A的构造函数的时候,默认会调用父类B的构造函数,在调用父类B构造函数的时候,秘密的传进去的当前实例是 A的实例—-因为是在A的构造函数中调用的B,所以,这个地方的this反而代表了A。
本文转载自:https://my.oschina.net/kalo/blog/333202,感谢作者kalo 。
阅读全文
0 0
- java中this关键字
- Java中this关键字
- java中this关键字
- java中this关键字
- java中this关键字
- java中this关键字
- Java中this关键字
- java中This关键字
- java中this关键字
- java中this关键字
- Java中this关键字
- Java中this关键字
- java中this关键字
- Java中this关键字
- java中this关键字
- java中this关键字
- java中this关键字用法
- java中this关键字使用
- 数据保存!!!Python 爬取网页数据后,三种保存格式---保存为txt文件、CSV文件和mysql数据库
- iTop系统使用手册
- Hadoop 2.7.4伪分布式安装步骤与排坑
- taskAffinity和allowTaskReparenting的实例
- Android studio NDK编译及so库生成方法讲解
- Java中this关键字
- 严重: Parse Fatal Error at line 2 column 243: 已经为元素 "web-app" 指定属性 "xmlns"。 org.xml.sax.SAXParseExcept
- 数据结构思维 第七章 到达哲学
- 5大算法思想
- 算法 第四版 1.4.14 4-sum
- CTS,GTS,CTS Verifier失败项总结(持续更新)
- Android Butterknife(黄油刀) 使用方法总结
- 对于关系型数据库中的索引的基本理解
- 数位dp 模板