this关键字的四种用法
一、this.属性名
表示对象自己的属性使用this调用成员变量,解决变量与局部变量之间的冲突问题
1.实例分析
代码如下(示例):
public class Person{public String name;public int age;public double height;public Person(String name,int a,double height){name=name;age=age;height=height;}public void introduce(){System.out.println("我叫"+name+",今年"+age+"岁");}}
2.测试代码
代码如下(示例):
public static void main(String[] args){Person person = new Person("张三",20,178.5);person.introduce();}
控制台运行结果:
我叫null,今年0岁
分析:为什么会出现这种情况呢?当我们调用构造方法所传递的三个参数值“张三”、20和178.5最终并没有赋值到对象的三个属性中。那么,既然参数值没有被赋值到对象中,他们去了哪里呢?当构造方法的参数与类所定义的属性同名,根据“同名情况下,局部变量的优先级更高”原则,在构造方法执行的过程中,虚拟机会把参数值赋给参数本身,而不是赋值给对象的属性!具体来说,就是我们给构造方法的name参数传递法的值是“张三”最终没有被赋值到对象的name属性中,才导致introduce方法中打印出的name属性是null。当然,age和height这两个参数也是同样的赋值效果。
3.改进代码
为了能够让虚拟机明白我们所期望的是:把“张三”这个字符串赋值给对象的name属性中,而不是“再一次”把它赋值给构造方法的参数,就需要把构造方法中的赋值语句作出如下修改:
public Person(String name,int age,double height){this.name=name;this.age=age;this.height=height;}
运行测试,控制台结果如下:
我叫张三,今年20岁
二、this.方法名
表示本对象自己的方法
我们给Person类增加了一个“打招呼”的方法叫做greet。在introduce方法当中,就可以通过“this。方法名”的方式来调用这个方法,表示调用的是“本对象自己的greet方法”。这是this关键字的第二种方法。当然,在introduce方法中并没有出现其他对象,所以方法名前面的this关键字也可以省略不写。
public void greet(){System.out.println("hello,大家好");}public void introduce(){this.greet();System.out.println("我叫"+name+",今年"+age+"岁");}
测试程序,结果如下:
hello,大家好我叫张三,今年20岁
三、this关键字用法三
除此之外this关键字还有一种很重要的方法,那就是在this关键字的后面加上小括号,这样就表示调用了某个类自身的构造方法,我们修改一下Person类:
//构造方法1public Person(String name,int age,double height){this(name,age);//调用构造方法2this.height=height;}//构造方法2public Person(String name,int age){this.name=name;this.age=age;}
在构造方法1中,通过“this(参数);”的方式调用了构造方法2.这就是this关键字的有一种用法。那么为什么要通过这种方式来调用构造方法呢?难道不能直接写一个“Person(name,age);”来调用吗?在java语言中,一个类的构造方法与类名相同。但是一个类当中也可以定义一个与类名相同的普通方法,换句话说:并不是只有构造方法与类名相同,普通方法也可以取和类名相同的名称(不过没人会这么干)。那么,在这种情况下,编译器如何区分这个方法是普通方法还是构造方法呢?很简单,普通方法的名称前面必须定义返回值类型,而构造方法的前面没有返回值类型的定义。这样,编译器就能够分清那个是构造方法,哪个是和类名相同的普通方法。
定义分的清,但是在调用的时候,都是通过方法名来调用的,这是该如何分的清代码中哪一句调用的是构造方法,哪一句调用的是普通方法呢?为了解决这个问题,JAVA语言规定,在本类中调用构造方法的时候,需要通过“this(参数)”的方法来调用。除此之外,Java语言还规定了这种调用方式所必须遵循的规则。首先,这种“this(参数)”方式只能在“其他构造方法中使用”,不能在普通方法中使用。如果在普通方法中使用,将会被视为语法错误,如下代码:
public void greet(){this("张三",20);//此处代码错误,不能再普通方法中调用Systen.out.println("hello,大家好");}
其次,在一个构造方法中,用“this(参数)”的形式调用构造方法,”this(参数)”必须写在主调方法的第一行。第三,不能出现相互循环调用,也就是说,不能在构造方法1中调用方法2,有同时在构造方法2中调用方法1,如下:
//构造方法1public Person(String name,int age,double height){this(name,age);//在构造方法1中调用构造方法2this.height=height;}//构造方法2public Person(String name,int age){this(name,agem,178.5);//在构造方法2中调用构造方法1}
四、外部类名.this.属性
this关键字在我们编写内部类代码的时候,还有一种用途,那就是区分属性或方法的具体归属
代码如下(示例):
public class Outter{public int a=0;//外部类的属性class Inner{public void printA(){System.out.ptintln(a);//内部类方法调用外部类的属性}}}
测试代码:
public static void main(String[] args){//先创建外部类Outter outter = new Outter();//在创建外部类的内部类Outter.Intter inner = outter.new Inner();inner.printA();}
运行结果:
0//表示内部类方法调用外部类的属性
分析:在这段代码中,定义了外部类Outter,Outter有一个属性a,并且Outter中又定义了内部类,在内部类的print()方法中调用了外部类的a属性。我们都知道,一个内部类可以直接访问它所在外部类的属性和方法。这个特性在我们的上面这段代码中得到了体现。但是,如果内部类中出现了与外部类同名的属性或者方法时,该如何区分调用的到底是哪个属性或方法呢?比如说,在Inner类中也出现了a属性,那么输出语句中的a到底是指哪个a呢?其实很简单,如果输出语句中直接写a,那么调用的是内部类的a属性。为了强调它是内部类的a属性,我们也可以在a的前面加this关键字。如果我们希望调用的是外部类的a属性,可以用“外部类名.this.a”的方式来调用。
代码示例:
public class Outter{public inbt a=0;//外部类的属性class Inner{public int a=10;//内部类的属性public void printA(){System.out.ptintln(a);//调用内部类的a属性,输出10System.out.println(this.a);//调用内部类的a属性,输出10System.out.println(Outter.this.a);//调用外部类的a属性,输出0}}}
总结
注意:
因为this是在对象内部指代自身的引用,所以this只能调用实例变量、实例方法和构造方法,不能调用类变量和类方法,也不能调用局部变量。