Java中this关键字底层原理

this关键字大家都很熟悉,天天见到,主要有以下三个用途 :

1.this调用本类中的属性,也就是类中的成员变量;

2.this调用本类中的其他方法;

3.this调用本类中的其他构造方法(只能引用一个构造方法且必须位于首行)。

简单的如何使用,这里就跳过了,本文主要是分析原理,这里需要有点点jvm的知识,不过我也会介绍的。

下面进入正题:当我们在方法内部使用this调用属性、方法的时候,你有没有考过this是怎么来的?作为引用变量,this的数据类型是什么?我们在代码里写的this,编译成字节码文件后变成了什么?jvm又是如何处理this的呢?

看看我们平时写的代码xxx.Java编译后变成了什么,经过javap反编译后的xxxx.class如下(:

下面大概解释一下上面的乱七八糟的一坨:首先想看的十分明白需要查看JVM的指令https://blog.csdn.net/evanxuhe/article/details/81195851和了解JVM中调用方法时的栈帧的原理,先不管他,后面准备再写一篇JVM的理解,这里只需要看个大概就可以了,下面分析的有点点乱,一定要对比上面的两个截图仔细看。
一。4-19行:Base类的默认的constructor,当然了,我们代码里面没有显式的定义constructor,但是编译的时候编译器会帮我们创建一个无参的constructor,和我们手动定义一个方法体为空的无参constructor效果完全一样。 
其中7-13行是构造方法的代码区域;第17-19行描述的是Java源码中定义的局部变量与该方法被执行时栈帧中的局部变量表中的变量的对应关系。第7行args_size=1,说明构造方法有一个参数,那我们就看下第17-19行的LocalVariableTbale中这个参数到底是什么。我们发现,这个唯一的局部变量就是this!且其静态类型为Base!: 
二。10-12行,是给实例变量name进行初始化赋值。即实例变量的初始赋值操作,是在构造方法中进行的。
21-31行:instanceMethod实例方法。同样我们看到字节码文件中却有两个参数,args_size=2,第一个参数是this,且参数的静态类型为Base!
33-39行:classMethod静态方法,属于类的。我们可以明确的看到args_size=1,即只有我们自己定义的参数str2。类方法(静态方法)中,并没有this局部变量!当然,我们也就无法在类方法中使用this关键字了!

总结一下:

1. 构造方法、实例方法的第一个参数是this!这是由编译器自动添加的(回头看看4-19行的默认构造方法的逻辑,第八行的aload_0指令就是将this引用推送至栈顶,即压入栈)。 
2. this引用变量的数据类型是this所在方法的所属类。即编码时,this出现在哪个类中,this的数据类型就是这个类(回头看看17-19行,默认的无参构造方法这个唯一的局部变量就是this!且其静态类型为Base!)。 
3. 既然编译器会自动给实例方法添加一个this参数,那么就不难理解,当调用某个实例对象的方法时,编译器会将该实例对象当做参数传递到调用方法中了,这也是我们能在无参的方法中使用this的原因。

     1.静态方法和静态代码块中不能使用this

     2.实例方法中(非构造非静态):this指代的是正在调用当前方法的对象

     3.构造方法中:this指代的是正在new的对象本身,

下面讲一下static的情况:为什么静态的就不能使用this呢,其实这是跟类加载的机制有关,我们知道静态方法是可以直接通过类名直接调用的,根本没有实例化一个对象,因为无论静态方法和静态代码块在对象实例化之前的的类加载的时候就已经执行了,这时候对象还没出生呢,this也不存在呢,相当于静态的方法的参数中没有this这个参数,所以Java语法中静态方法中不让你调用this。

最后说的有点乱,再总结一下:

1. this指代的一定是对象,是jvm堆中的某个class的实例对象的引用;this代表的不是class或者其他。 
2. this出现的位置一般是在方法体内部(包括方法参数位置),假设this在methodA中出现,那么this指代的就是正在调用methodA的那个对象;即便this出现在方法体外部。如,假设在class A 中定义成员变量 A a = this; 最终这行代码仍然会被放入class A 的到构造函数中执行。 
3. 为了便于理解,对this在普通方法和构造方法中进行了区分。其实,构造方法的真正功能是对对象进行初始化。 
实际上,在jvm层面上,在执行构造方法之前,jvm已经为在堆中给对象分配好了内存空间,并将该对象的引用当做参数传递到构造方法中,构造方法的执行,只是为了给对象进行初始化。所以,我们仍然可以按照第一条表述来理解,即,构造方法是由新创建的对象来调用的,构造方法中的this,仍然指代的是正在调用该构造方法的对象。

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值