当前位置: 首页 > 后端技术 > Java

Java中this和super的用法详解

时间:2023-04-02 09:07:41 Java

前言Java中的关键字上一篇我们讲了final,深入理解了Java中的final关键字。这次我们来回顾一下关键字this和super的用法。作为一个Java程序员,我觉得基础是最重要的,因为它决定了我们的上限,所以我的大部分文章都是以分享Java基础知识为主。把事情简单化。话不多说,让我们进入正文。thisthis关键字只能在方法内部使用,以指示对调用该方法的对象的引用。其实简单来说,this关键字就是当前对象的意思。下面详细介绍下this关键字在Java中的用法。1.调用成员变量是在类的方法内部。如果我们想调用它的成员变量而不用this,怎么办呢?publicclassThisTest{privateStringname="xiaoming";publicStringgetName(){返回名称;}publicvoidsetName(Stringname){name=name;}}看上面的代码,我们在ThisTest类的属性中创建了一个name,然后创建了一个setName方法,注意这个方法的形参也是一个Stringname,那么我们通过name=name赋值,将它改变了成员变量名的属性?publicstaticvoidmain(String[]args){ThisTestthisTest=newThisTest();thisTest.setName("小马");System.out.println(thisTest.getName());}打印结果是xiaoming,不是usresetxiaoma,显然,这个方法不能调用方法内部的成员变量。因为形参的名字和成员变量的名字一样,setName方法里面的name=name,根据就近原则,编译器默认把两个name属性都解析成形参名字,这就导致了我们的设置操作和成员变量名完全无关,当然不能设置。解决方案是使用this关键字。我们修改setName方法如下:publicvoidsetName(Stringname){this.name=name;}调用上面的main方法赋值,打印结果为xiaoma。this代表当前对象,即调用该方法的对象,object.name必须是调用的成员变量。2.调用构造函数构造函数是一个与类同名的方法。构造函数没有返回值,但不能用void修饰。在一个类中,必须有一个构造函数。如果没有,编译器会在编译时自动给类添加一个无参构造函数。一个类可以有多个构造函数,调用时根据参数来区分。公共课学生{私人年龄;私有字符串名称;publicStudent(){this("Pony",50);}publicStudent(Stringname,intage){this.name=name;这个。年龄=年龄;System.out.println(姓名+“今年”+年龄+“旧”);}publicstaticvoidmain(String[]args){Studentstudent01=newStudent();Studentstudent02=newStudent("小军",45);}}通过this("小马",50)调用另一个构造函数Student(Stringname,intage)对成员变量进行初始化赋值。输出结果:小马今年50岁小军今年45岁Processfinishedwithexitcode0注意:通过this调用构造函数,只能将这段代码放在构造函数的第一行,即编译器的规定是:如果放在第二行,就会报错。3.调用常用方法。这代表当前对象,所以你当然可以调用当前类的公共方法。publicStudent(){this.say();}publicvoidsay(){System.out.println("小马唱歌很好听。");}4.返回当前对象publicclassThisTest{publicObjectnewObject(){返回这个;}}这意味着无论谁调用newObject()方法,都将返回对谁的引用。superJava中的super关键字是对父类对象的引用。我们在这句话中分析父类对象的引用,也就是说我们在使用的时候只能在子类中使用。既然是对象的引用,我们也可以用它来调用成员属性和成员方法。当然这里的super关键字也可以调用父类的构造函数。具体有以下几种用法:1.调用父类的构造函数。Java中的继承大家应该都懂。子类继承父类。我们可以使用子类的对象来调用父类的属性和方法。我们知道属性和方法只能通过对象来调用,那么我们可以做一个大胆的假设:在创建子类对象的同时,我们也创建了父类的对象,而创建对象是通过调用构造函数来实现的,那么我们创建一个子类对象,应该调用父类的构造函数。我们看这段代码:publicclassTeacher{publicTeacher(){System.out.println("我是人民教师。");}}classStudentextendsTeacher{publicStudent(){System.out.println("我是学生。");}}下面我们创建一个子类对象:publicstaticvoidmain(String[]args){Students=newStudent();}输出:我是人民教师。我是一名学生。Processfinishedwithexitcode0通过打印结果可以看出,在创建子类对象时,首先调用父类的构造函数,然后再调用子类的构造函数,也就是说,在创建子类时对象,我们先创建父类对象得到,这和我们之前的猜想是一致的。那么问题又来了:什么时候调用父类的构造函数?可以参考Java官方文档:https://docs.oracle.com/javas...红框内的英文翻译是:如果声明的类是原始类Object,则默认构造函数体为空.否则,默认构造函数只调用不带参数的超类构造函数。也就是说:除了顶层类Object的构造函数。是对象)。那它叫什么?我们看一下官方文档:上面的意思大概是:通过super关键字调用超类构造函数,以super关键字开头。所以上面Student类的构造方法其实应该是这样的:classStudentextendsTeacher{publicStudent(){super();//子类通过super调用父类的构造方法System.out.println("我是一名学生。”);}publicstaticvoidmain(String[]args){Students=newStudent();}}默认情况下,子类通过super()调用父类的无参构造函数,如果父类显示的是声明了有参构造函数而没有声明无参构造函数,则在实例化子类时会报错。解决方法是使用super关键字调用父类的有参构造函数:classStudentextendsTeacher{publicStudent(){super("Pony");System.out.println("我是学生。");}publicstaticvoidmain(String[]args){Students=newStudent();}}2.调用父类的成员属性publicclassTeacher{publicStringname="Pony";publicTeacher(){System.out.println("我是人民的老师。");}}classStudentextendsTeacher{publicStudent(){System.out.println("我是学生。");}publicvoidfatherName(){System.out.println("我的父类名字是:"+super.name);//调用父类的属性}publicstaticvoidmain(String[]args){Studentstudent=newStudent();student.fatherName();}}输出结果:我是人民教师我是学生我的父类名称是:PonyProcessfinishedwithexitcode03,调用父类public类的方法Teacher{publicStringname;publicTeacher(){System.out.println("我是人民教师。");}publicvoidsetName(Stringname){this.name=name;}}classStudentextendsTeacher{publicStudent(){super();//调用父类System.out.println("我是学生。");}publicvoidfatherName(){super.setName("小君");//调用父类的普通方法System.out.println("我的父类名字是:"+super.name);//调用父类的属性}publicstaticvoidmain(String[]args){Studentstudent=newStudent();student.fatherName();}}输出:我是人民教师我是学生我父类名称为:XiaojunProcessfinishedwithexitcode04,this和super出现在同一个构造方法中?假设super()通过this()关键字前的super()调用父类构造方法,是的父类实例化一次,然后调用this(),this()方法会调用子类的构造函数,父类又会在子类的构造函数中实例化一次,也就是说我们要实现子类一次实例化导致父类的两次实例化,那么显然编译器是不允许的,反之this()在super()之前也是一样的。并且编译器对this()和super()有限制。这两个关键字只能出现在构造方法的第一行。把这两个关键字放在一起,第二行总有一个关键字,编译是不会通过的。this和super的异同super(parameter):在基类中调用一个构造函数(应该是构造函数中的第一条语句)。this(参数):调用本类的另一个构造函数(应该是构造函数中的第一条语句)。super: 引用当前对象的直接父类的成员(用于访问隐藏成员数据或父类在直接父类中的函数,当基类和派生类有相同的成员定义时,如:super.变量名,super.成员函数数据名(实参).this:代表名字当前对象的(在程序中容易出现歧义的地方,应该用this来指明当前对象;如果函数形式参与类的成员数据同名,则必须用this来指明成员变量名)调用super()必须写在子类构造方法的第一行,否则会编译失败。每个子类构造方法的第一条语句隐式调用super()。如果父类没有这种形式的构造函数,编译时就会报错。super()与this()类似,区别在于super()从子类调用父类的构造函数,而this()调用同一个类中的其他方法。super()和this()都需要放在构造函数的第一行。虽然你可以用这个调用一个构造函数,但你不能调用两个。this和super不能同时出现在一个构造函数中,因为this必然会调用其他的构造函数,而其他的构造函数也必须有super语句,所以如果同一个构造函数中有相同的语句,就会丢失。语句的意思,编译器不会通过。this()和super()都引用对象,因此都不能在静态环境中使用。包括:静态变量、静态方法、静态语句块。本质上,this是指向此对象的指针,而super是Java关键字。说到底,我是一个被打击了还在努力的码农。如果文章对你有帮助,记得点赞关注,谢谢!