关于java:Java-中-this-和-super-的用法详解

49次阅读

共计 5017 个字符,预计需要花费 13 分钟才能阅读完成。

前言

Java 中的关键字上篇咱们讲到了 final,深刻了解 Java 中的 final 关键字
,这次咱们来回顾一下thissuper这两个关键字的用法,作为一名 Java 程序员,我感觉根底是最重要的,因为它决定了咱们的下限,所以我的文章大部分还是以分享 Java 基础知识为主,学好根底,前面的常识我想学起来就变得简略。废话不多说,进入注释。

this

this 关键字只能在办法外部应用,示意对 调用办法的那个对象 的援用。

其实简略来说 this 关键字就是示意以后对象,上面咱们来具体介绍 this 关键字在 Java 中的用法。

1、调用成员变量

在一个类的办法外部,如果咱们想调用其成员变量,不必 this,咱们会怎么做?

public class ThisTest {

    private String name = "xiaoming";

    public String getName() {return name;}

    public void setName(String name) {name = name;}
}

看下面的代码,咱们在 ThisTest 类中创立了一个 name 属性,而后创立了一个 setName 办法,留神这个办法的形参也是 String name,那么咱们通过 name = name 这样赋值,会扭转成员变量 name 的属性吗?

public static void main(String[] args) {ThisTest thisTest = new ThisTest();
    thisTest.setName("xiaoma");
    System.out.println(thisTest.getName());
}

打印后果是 xiaoming,而不是咱们从新设置的 xiaoma,显然这种形式是不能在办法外部调用到成员变量的。因为形参的名字和成员变量的名字雷同,setName 办法外部的 name = name,依据最近准则,编译器默认是将这两个 name 属性都解析为形参 name,从而导致咱们设值操作和成员变量 name 齐全没有关系,当然设置不了。

解决办法就是应用 this 关键字。咱们将 setName 办法批改如下:

public void setName(String name) {this.name = name;}

在调用下面的 main 办法进行赋值,打印的后果就是 xiaoma了。

this 示意以后对象,也就是调用该办法的对象,对象.name 必定就是调用的成员变量。

2、调用构造方法

构造方法是与类同名的一个办法,构造方法没有返回值,然而也不能用 void 来润饰。在一个类中,必须存在一个构造方法,如果没有,编译器会在编译的时候主动为这个类增加一个无参构造方法。一个类可能存在多个构造方法,调用的时候依据参数来辨别。

public class Student {

    private int age;

    private String name;

    public Student() {this("小马",50);
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println(name + "往年" + age + "岁了");
    }


    public static void main(String[] args) {Student student01 = new Student();
        Student student02 = new Student("小军",45);
    }
}

通过 this("小马",50) 来调用另外一个构造方法 Student(String name, int age) 来给成员变量初始化赋值。

输入后果:

小马往年 50 岁了
小军往年 45 岁了

Process finished with exit code 0

留神:通过 this 来调用构造方法,只能将这条代码放在构造函数的第一行,这是编译器的规定,如下所示:放在第二行会报错。

3、调用一般办法

this 示意以后对象,那么必定可能调用以后类的一般办法。

public Student() {this.say();
}

public void say(){System.out.println("小马很会唱歌。");
}

4、返回以后对象

public class ThisTest {public Object newObject(){return this;}
}

这示意的意思是谁调用 newObject() 办法,那么就返回谁的援用。

super

Java 中的 super 关键字则是示意 父类对象的援用

咱们剖析这句话 父类对象的援用,那阐明咱们应用的时候只能在子类中应用,既然是对象的援用,那么咱们也能够用来调用成员属性以及成员办法,当然了,这里的 super 关键字还可能调用父类的构造方法。

具体有如下几种用法

1、调用父类的构造方法

Java 中的继承大家都应该理解,子类继承父类,咱们是可能用子类的对象调用父类的属性和办法的,咱们晓得属性和办法只可能通过对象调用,那么咱们能够大胆假如一下:在创立子类对象的同时,也创立了父类的对象,而创建对象是通过调用构造函数实现的,那么咱们在创立子类对象的时候,应该会调用父类的构造方法。

上面咱们看这段代码:

public class Teacher {public Teacher(){System.out.println("我是一名人民老师。");
   }
}

class Student extends Teacher {public Student(){System.out.println("我是一名学生。");
    }
}

上面咱们创立子类的对象:

public static void main(String[] args) {Student s = new Student();
}

输入后果:

我是一名人民老师。我是一名学生。Process finished with exit code 0

通过打印后果看到咱们在创立子类对象的时候,首先调用了父类的构造方法,接着调用子类的构造方法,也就是说在创立子类对象的时候,首先创立了父类对象,与后面咱们猜测的统一。

那么问题又来了:是在什么时候调用的父类构造方法呢?

能够参考 Java 官网文档:https://docs.oracle.com/javas…

红色框内的英文翻译为:如果申明的类是原始类 Object,那么默认的构造函数有一个空的主体。否则,默认构造函数只是简略地调用没有参数的超类构造函数。

也就是说:除了顶级类 Object.class 构造函数没有调用父类的构造方法,其余的所有类都默认在构造函数中调用了父类的构造函数(没有显式申明父类的子类其父类是 Object)。

那么是通过什么来调用的呢?咱们接着看官网文档:

下面的意思大略就是:超类构造函数通过 super 关键字调用,并且是以 super 关键字结尾。

所以下面的 Student类的构造方法实际上应该是这样的:

class Student extends Teacher {public Student(){super();// 子类通过 super 调用父类的构造方法
        System.out.println("我是一名学生。");
    }


    public static void main(String[] args) {Student s = new Student();
    }
}

子类默认是通过 super() 调用父类的无参构造方法,如果父类显示申明了一个有参构造方法,而没有申明无参构造方法,实例化子类是会报错的。

解决办法就是通过 super 关键字调用父类的有参构造方法:

class Student extends Teacher {public Student(){super("小马");
        System.out.println("我是一名学生。");
    }


    public static void main(String[] args) {Student s = new Student();
    }
}

2、调用父类的成员属性

public class Teacher {

    public String name = "小马";

    public Teacher() {System.out.println("我是一名人民老师。");
    }
}

class Student extends Teacher {public Student() {System.out.println("我是一名学生。");
    }

    public void fatherName() {System.out.println("我的父类名字是:" + super.name);// 调用父类的属性
    }

    public static void main(String[] args) {Student student = new Student();
        student.fatherName();}
}

输入后果:

我是一名人民老师。我是一名学生。我的父类名字是:小马

Process finished with exit code 0

3、调用父类的办法

public class Teacher {

    public String name;

    public Teacher() {System.out.println("我是一名人民老师。");
    }

    public void setName(String name){this.name = name;}
}

class Student extends Teacher {public Student() {super();// 调用父类的构造方法
        System.out.println("我是一名学生。");
    }

    public void fatherName() {super.setName("小军");// 调用父类一般办法
        System.out.println("我的父类名字是:" + super.name);// 调用父类的属性
    }

    public static void main(String[] args) {Student student = new Student();
        student.fatherName();}
}

输入后果:

我是一名人民老师。我是一名学生。我的父类名字是:小军

Process finished with exit code 0

4、this 和 super 呈现在同一个构造方法中?

假如 super()this() 关键字的后面

首先通过 super() 调用父类构造方法,对父类进行一次实例化。接着调用 this()this() 办法会调用子类的构造方法,在子类的构造方法中又会对父类进行一次实例化。也就是说咱们对子类进行一次实例化,对造成对父类进行两次实例化,所以显然编译器是不容许的。

反过来 this()super() 之前也是一样。而且编译器有限定 this()super() 这两个关键字都只能呈现在构造方法的第一行,将这两个关键字放在一起,总有一个关键字在第二行,编译是不能通过的。

this 和 super 异同

  • super(参数)调用基类中的某一个构造函数(应该为构造函数中的第一条语句)。
  • this(参数)调用本类中另一种造成的构造函数(应该为构造函数中的第一条语句)。
  • super: 它援用以后对象的间接父类中的成员(用来拜访间接父类中被暗藏的父类中成员数据或函数,基类与派生类中有雷同成员定义时如:super. 变量名super. 成员函数据名(实参)
  • this:它代表以后对象名(在程序中易产生二义性之处,应应用 this 来指明以后对象;如果函数的形参加类中的成员数据同名,这时需用 this 来指明成员变量名)。
  • 调用 super() 必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用 super(),如果父类没有这种模式的构造函数,那么在编译的时候就会报错。
  • super()this() 相似, 区别是,super() 从子类中调用父类的构造方法,this() 在同一类内调用其它办法。
  • super()this() 均需放在构造方法内第一行。
  • 只管能够用 this 调用一个结构器,但却不能调用两个。
  • thissuper 不能同时呈现在一个构造函数外面,因为 this 必然会调用其它的构造函数,其它的构造函数必然也会有 super 语句的存在,所以在同一个构造函数外面有雷同的语句,就失去了语句的意义,编译器也不会通过。
  • this()super() 都指的是对象,所以,均不能够在 static 环境中应用。包含:static 变量,static 办法,static 语句块
  • 从实质上讲,this 是一个指向本对象的指针,然而 super 是一个 Java 关键字。

结尾

我是一个正在被打击还在致力后退的码农。如果文章对你有帮忙,记得点赞、关注哟,谢谢!

正文完
 0