哥哥,叫姐夫感觉如何?三姐恶狠狠的对我说,眼里满是不屑。“说实话,这种感觉还不错。”我有些不好意思的回答她:“不过,有一件事让我有些失落,大家好像都在关注你的容貌,完全忽略了我的盛世美颜!”哥,你在想什么?因为你的文章写得好,不然没人知道我是谁!有你这样的弟弟,我感到很自豪。”三姐沉声道:“咱们就说今天吧。我们要学什么?”“姐姐,我喜欢你说的。今天就来学习一下Java中的this关键字吧。”喝了一口农夫山泉,我对三姐说道。指向当前对象的变量。”我简单笑着继续说,“另外,this关键字还可以完成下面的工作。”调用当前类的方法;this()可以调用当前类的构造函数;this可以在方法中作为参数传递;this在构造函数中可以作为参数传递;this可以作为方法的返回值,返回类的当前对象。01.指向当前对象“三妹,让我们看下面的代码。”话音刚落,我就敲击了键盘。publicclassWithoutThisStudent{Stringname;intage;WithoutThisStudent(Stringname,intage){name=name;age=age;}voidout(){System.out.println(name+""+age);}publicstaticvoidmain(String[]args){WithoutThisStudents1=newWithoutThisStudent("沉默之王二",18);WithoutThisStudents2=newWithoutThisStudent("沉默之王三",16);s1.out();s2.out();}}"上例中构造的参数名method和实例变量名是一样的,因为没有使用this关键字,所以不能给实例变量赋值。”我抬起右手食指,指了指屏幕上的名字和年龄,对三妹说道。"看程序的输出"null0null0"从结果可以看出,虽然在创建对象的时候传递了参数,但是并没有给实例变量赋值。这是因为如果在构造方法,name和age指向的不是实例变量而是参数本身。”我把脖子扭到右边,看着三妹说道。“那我们怎么解决这个问题呢?大哥。”三姐着急的问道。“如果参数名和实例变量名有冲突……”我正要给出答案,三妹打断了我的话。“你要用这个吗?”三姐脱口而出。“哇,越来越好了,你。”感觉三妹在学习Java的道路上逐渐有了积极思考的意愿。“对,我们看一下添加this关键字后的代码。”安静的房间里,又是一阵噼里啪啦的键盘声。publicclassWithThisStudent{Stringname;intage;WithThisStudent(Stringname,intage){this.name=name;this.age=age;}voidout(){System.out.println(name+""+age);}publicstaticvoidmain(String[]args){WithThisStudents1=newWithThisStudent("沉默之王2",18);WithThisStudents2=newWithThisStudent("沉默之王3",16);s1.out();s2.out();}}》看程序输出”沉默王二18沉默王三16“这次实例变量是有值的,在构造方法中,this.xxx指向的是实例变量,而不是参数本身。我缓缓地说:“当然,如果参数名和实例变量名不一样,可以不用this关键字,但我建议用this关键字,这样的代码更有意义。”03.调用当前类的方法“三妹仔细听,看我打字够不够快”。publicclassInvokeCurrentClassMethod{voidmethod1(){}voidmethod2(){method1();}publicstaticvoidmain(String[]args){newInvokeCurrentClassMethod().method1();}}"三妹你仔细看,看到上面代码中的this关键字了吗?”我脸上带着神秘的笑容,准备给三妹变个魔术。“没错,兄弟,我已经确认过了。”“那么,神奇的事情就要发生了。”我突然觉得刘潜着了魔。很快在classes目录下找到InvokeCurrentClassMethod.class文件,双击打开(IDEA默认会使用FernFlower打开字节码文件)。publicclassInvokeCurrentClassMethod{publicInvokeCurrentClassMethod(){}voidmethod1(){}voidmethod2(){this.method1();}publicstaticvoidmain(String[]args){(newInvokeCurrentClassMethod()).method1();}}睁大眼睛仔细看,三妹,这个关键字出现了吗?”“哇,真的,太厉害了!”三妹也很努力配合我的表现。“我们可以在一个类中使用this关键字来调用另一个方法,如果没有使用,编译器会自动为我们添加。”我对自己深厚的编程功底充满信心,“在源代码中,method2()在调用method1()时并没有使用this关键字,但通过反编译后的字节码可以看出。”04.调用当前类的构造函数“看下面的代码”。publicclassInvokeConstrutor{InvokeConstrutor(){System.out.println("hello");}InvokeConstrutor(intcount){this();System.out.println(count);}publicstaticvoidmain(String[]args){InvokeConstrutorinvokeConstrutor=newInvokeConstrutor(10);}}"在带参数的构造方法InvokeConstrutor(intcount)中,通过this()调用不带参数的构造方法InvokeConstrutor()。"这一次,我换成了左手的食指,指着屏幕对三妹说:“this()可以用来调用当前类的构造函数——构造函数可以重用。”“看看输出。”hello10“真的,无参数构造函数也被调用了,所以程序输出hello。”三妹看到输出后不假思索的说道。也可以在无参构造方法中使用this(),传递参数调用有参构造方法。”话音落下,我在键盘上敲击,“看下面的代码。“publicclassInvokeParamConstrutor{InvokeParamConstrutor(){this(10);System.out.println("hello");}InvokeParamConstrutor(intcount){System.out.println(count);}publicstaticvoidmain(String[]args){InvokeParamConstrutorinvokeConstrutor=newInvokeParamConstrutor();}}"让我们再看看程序的输出。"10hello"但是要注意this()一定要放在构造方法的第一行,否则会报错。《05.在方法中作为参数传递》看下面的代码。“publicclassThisAsParam{voidmethod1(ThisAsParam){System.out.println(p);}voidmethod2(){method1(this);}publicstaticvoidmain(String[]args){ThisAsParamthisAsParam=newThisAsParam();System.out.println(thisAsParam);thisAsParam.method2();}}“this关键字可以在方法中作为参数传递,此时指向当前类的对象。”一不小心,半小时过去了,感觉冒烟了说到嗓子眼儿,赶紧又喝了一口水润了润嗓子继续说。“看输出就明白了,三姐。"com.itwanger.twentyseven.ThisAsParam@77459877com.itwanger.twentyseven.ThisAsParam@77459877"method2()调用method1()传递参数this,method1()打印当前对象的字符串。thisAsParam对象的字符串打印在main()方法中。从输出可以看出,两者是同一个对象。《06.在构造函数中作为参数传递》继续看代码。“publicclassThisAsConstrutorParam{intcount=10;ThisAsConstrutorParam(){Datadata=newData(this);data.out();}publicstaticvoidmain(String[]args){newThisAsConstrutorParam();}}classData{ThisAsConstrutorParamparam;Data(ThisAsConstrutorParamparam){this.param=param;}voidout(){System.out.println(param.count);}}”在构造方法ThisAsConstrutorParam()中,我们使用this关键字作为参数传递给Data对象,它实际上指向newThisAsConstrutorParam()这个对象。""this关键字也可以在构造函数中作为参数传递,它指向当前类的对象。当我们需要在多个类中使用一个对象时,这非常有用。“”看看输出。”1007,作为方法的返回值,“需要休息吗?三姐”“没事,哥,我注意力还是很集中的,你继续说吧。”“好,我们继续看代码。“publicclassThisAsMethodResult{ThisAsMethodResultgetThisAsMethodResult(){returnthis;}voidout(){System.out.println("hello");}publicstaticvoidmain(String[]args){newThisAsMethodResult().getThisAsMethodResult().out();}}"getThisAsMethodResult()方法返回this关键字,指向新的ThisAsMethodResult()对象,所以可以立即调用out()方法——达到了链式调用的目的,这也是this关键字非常经典的用法。""链式调用的形式在JavaScript代码中更为常见。为了向三妹证明这一点,我打开了jQuery的源码。“原来有这么多连锁电话!”三美叹了口气。“是的。”我点点头,然后指着getThisAsMethodResult()方法的返回值对三妹说,“需要注意的是,当this关键字作为方法的返回值时,方法的返回类型是班级的类型。”“看输出。”你好”所以,这个关键字的介绍到此结束。活动一下僵硬的脖子,我对三姐说,“如果你还有动力学习,我们顺便把super关键字拿来怎么样?”“不用了,听说super关键字比较简单,我自己看看就好,不用你多说!”“不不不,三姐你要假装在听,不然我没法给读者解释。”“哎哟。”三姐意味深长地笑了笑。08.super关键字“super关键字主要有三种用法。"指向父类对象;调用父类的方法;super()可以调用父类的构造函数。“其实和这个有些相似,只是用意不太一样。”我拿起水瓶,又喝了几口,真渴。“每当创建子类对象时,都会隐式创建一个父类对象,由super关键字引用。”“如果父类和子类有同名字段,可以使用super关键字访问父类同名字段。”“看下面的代码。”publicclassReferParentField{publicstaticvoidmain(String[]args){newDog().printColor();}}classAnimal{Stringcolor="white";}classDogextendsAnimal{Stringcolor="black";voidprintColor(){System.out.println(color);System.out.println(super.color);}}"父类Animal中有一个名为color的字段,子类Dog字段中有一个名为color的字段,在子类的printColor()方法中,super关键字可用于访问父类的颜色。”“看看输出结果。”《黑与白》当子类和父类的方法名相同时,可以使用超级键Word来调用父类的方法。也就是说,当方法被重写时,可以使用super关键字来访问父类的方法。“publicclassReferParentMethod{publicstaticvoidmain(String[]args){newDog().work();}}classAnimal{voideat(){System.out.println("Eat...");}}classDogextendsAnimal{@Overridevoideat(){System.out.println("Eat...");}voidbark(){System.out.println("Wow,woof...");}voidwork(){super.eat();bark();}}“看,三姐。父类Animal和子类Dog都有一个名为eat()的方法,super.eat()可以访问父类的eat()方法。"趁着三妹消化自己的时间,我在键盘上敲完了一堆代码publicclassReferParentConstructor{publicstaticvoidmain(String[]args){newDog();}}classAnimal{Animal(){System.out.println("动物是coming");}}classDogextendsAnimal{Dog(){super();System.out.println("Thedogiscoming");}}"在子类Dog的构造方法中,第一行代码是super(),用于调用父类的构造函数。“”看看输出。“动物在这里,狗在这里。”当然,默认super()是可以省略的,编译器会主动调用父类的构造函数。也就是说,即使子类不使用super()主动调用父类的构造函数,父类的构造函数仍然会先执行。"publicclassReferParentConstructor{publicstaticvoidmain(String[]args){newDog();}}classAnimal{Animal(){System.out.println("动物来了");}}classDogextendsAnimal{Dog(){System.out.println("Herecomesthedog");}}"输出与之前相同。“动物来了,狗来了”super()也可以用来调用父类的参数化构造方法,可以提高代码的复用性。“classPerson{intid;Stringname;Person(intid,Stringname){this.id=id;this.name=name;}}classEmpextendsPerson{floatsalary;Emp(intid,Stringname,floatsalary){super(id,name);这。salary=salary;}voiddisplay(){System.out.println(id+""+name+""+salary);}}publicclassCallParentParamConstrutor{publicstaticvoidmain(String[]args){newEmp(1,"沉默之王2",20000f).display();}}"Emp类继承了Person类,也继承了id和name字段。当Emp加入salary字段后,构造函数可以使用super(id,name)调用父类的参数化构造函数。“”看看输出。”1沉默王二20000.0三姐点点头,想着一切。09,结尾“三妹,我们这里学习一下this和super的关键词。有什么问题吗?”三姐学习Java的热情让我对自己以后的编程生涯充满了信心。三姐笑道:“对了兄弟,《教妹学 Java》已经更新到第20讲了,别忘了同步更新你的PDF哦!”“一定。”三姐听了我的话,便安安心心的回了自己的茅屋休息去了。趁着她不在,把这篇文章编辑到“沉默王二”公众号,满怀期待的留言区等待新一波“大叔”。本文转载自微信公众号“沉默王二”,可通过以下二维码关注。转载本文请联系沉默王二公众号。
