this 和 super 有什么区别?this 能调用到父类吗?

简介: 我是小假 期待与你的下一次相遇 ~

1、super 关键字

super 是用来访问父类实例属性和方法的。

1.1 super 方法使用

每个实例类如果没有显示的指定构造方法,那么它会生成一个隐藏的无参构造方法。对于 super() 方法也是类似,如果没有显示指定 super() 方法,那么子类会生成一个隐藏的 super() 方法,用来调用父类的无参构造方法,这就是开篇所说的“每个类在实例化的时候之所以能调用到 Object 类,就是默认 super 方法起作用了”,接下来通过实例来验证一下这个说法。

PS:所谓的“显示”,是指在程序中主动的调用,也就是在程序中添加相应的执行代码。

  1. public class SuperExample {
  2.    // 测试方法
  3.    public static void main(String[] args) {
  4.        Son son = new Son();
  5.    }
  6. }
  7. /**
  8. * 父类
  9. */
  10. class Father {
  11.    public Father() {
  12.        System.out.println("执行父类的构造方法");
  13.    }
  14. }
  15. /**
  16. * 子类
  17. */
  18. class Son extends Father {
  19. }

在以上代码中,子类 Son 并没有显示指定 super() 方法,运行以上程序,执行的结果如下: 从上述的打印结果可以看出,子类 Son 在没有显示指定 super() 方法的情况下,竟然调用了父类的无参构造方法,这样从侧面验证了,如果子类没有显示指定 super() 方法,那么它也会生成一个隐藏的 super() 方法。这一点也可以从此类生成的字节码文件中得到证实,如下图所示:

super 方法注意事项

如果显示使用 super() 方法,那么 super() 方法必须放在构造方法的首行,否则编译器会报错,如下代码所示: 如上图看到的那样,如果 super() 方法没有放在首行,那么编译器就会报错:提示 super() 方法必须放到构造方法的首行。为什么要把 super() 方法放在首行呢?这是因为,只要将 super() 方法放在首行,那么在实例化子类时才能确保父类已经被先初始化了。

1.2 super 属性使用

使用 super 还可以调用父类的属性,比如以下代码可以通过子类 Son 调用父类中的 age 属性,实现代码如下:

  1. public class SuperExample {
  2.    // 测试方法
  3.    public static void main(String[] args) {
  4.        Son son = new Son();
  5.    }
  6. }
  7. /**
  8. * 父类
  9. */
  10. class Father {
  11.    // 定义一个 age 属性
  12.    public int age = 30;
  13.    public Father() {
  14.        super();
  15.        System.out.println("执行父类的构造方法");
  16.    }
  17. }
  18. /**
  19. * 子类
  20. */
  21. class Son extends Father {
  22.    public Son() {
  23.        System.out.println("父类 age:" + super.age);
  24.    }
  25. }

以上程序的执行结果如下图所示,在子类中成功地获取到了父类中的 age 属性:

2、this 关键字

this 是用来访问本类实例属性和方法的,它会先从本类中找,如果本类中找不到则在父类中找。

2.1 this 属性使用

this 最常见的用法是用来赋值本类属性的,比如常见的 setter 方法,如下代码所示: 上述代码中 this.name 表示 Person 类的 name 属性,此处的 this 关键字不能省略,如果省略就相当于给当前的局部变量 name 赋值 name,自己给自己赋值了。可以尝试一下,将 this 关键字取消掉,实现代码如下:

  1. class Person {
  2.    private String name;
  3.    public void setName(String name) {
  4.        this.name = name;
  5.    }
  6.    public String getName() {
  7.        return name;
  8.    }
  9. }
  10. public class ThisExample {
  11.    public static void main(String[] args) {
  12.        Person p = new Person();
  13.        p.setName("Fcant");
  14.        System.out.println(p.getName());
  15.    }
  16. }

以上程序的执行结果如下图所示: 从上述结果可以看出,将 this 关键字去掉之后,赋值失败,Person 对象中的 name 属性就为 null 了。

2.2 this 方法使用

可以使用 this() 方法来调用本类中的构造方法,具体实现代码如下:

  1. public class ThisExample {
  2.    // 测试方法
  3.    public static void main(String[] args) {
  4.        Son p = new Son("Java");
  5.    }
  6. }
  7. /**
  8. * 父类
  9. */
  10. class Father {
  11.    public Father() {
  12.        System.out.println("执行父类的构造方法");
  13.    }
  14. }
  15. /**
  16. * 子类
  17. */
  18. class Son extends Father {
  19.    public Son() {
  20.        System.out.println("子类中的无参构造方法");
  21.    }
  22.    public Son(String name) {
  23.        // 使用 this 调用本类中无参的构造方法
  24.        this();
  25.        System.out.println("子类有参构造方法,name:" + name);
  26.    }
  27. }

以上程序的执行结果如下图所示: 从上述结果中可以看出,通过 this() 方法成功调用到了本类中的无参构造方法。 :::tips 注意:this() 方法和 super() 方法的使用规则一样,如果显示的调用,只能放在方法的首行。 :::

2.3 this 访问父类方法

接下来,尝试使用 this 访问父类方法,具体实现代码如下:

  1. public class ThisExample {
  2.    public static void main(String[] args) {
  3.        Son son = new Son();
  4.        son.sm();
  5.    }
  6. }
  7. /**
  8. * 父类
  9. */
  10. class Father {
  11.    public void fm() {
  12.        System.out.println("调用了父类中的 fm() 方法");
  13.    }
  14. }
  15. /**
  16. * 子类
  17. */
  18. class Son extends Father {
  19.    public void sm() {
  20.        System.out.println("调用子类的 sm() 方法访问父类方法");
  21.        // 调用父类中的方法
  22.        this.fm();
  23.    }
  24. }

以上程序的执行结果如下: 从上述结果可以看出,使用 this 是可以访问到父类中的方法的,this 会先从本类中找,如果找不到则会去父类中找。

3、thissuper 的区别

1.指代的对象不同

super 指代的是父类,是用来访问父类的;而 this 指代的是当前类。

2.查找范围不同

super 只能查找父类,而 this 会先从本类中找,如果找不到则会去父类中找。

3.本类属性赋值不同

this 可以用来为本类的实例属性赋值,而 super 则不能实现此功能。

4.this 可用于 synchronized

因为 this 表示当前对象,所以this 可用于 synchronized(this){....} 加锁,而 super 则不能实现此功能。

总结

thissuper 都是 Java 中的关键字,都起指代作用,当显示使用它们时,都需要将它们放在方法的首行(否则编译器会报错)。this 表示当前对象,super 用来指代父类对象,它们有四点不同:指代对象、查找访问、本类属性赋值和 synchronized 的使用不同。

相关文章
|
5月前
|
缓存 Java Maven
说一说 Maven 依赖下载失败的问题总结分析
我是小假 期待与你的下一次相遇 ~
616 1
|
Java 数据库连接 开发者
Mybatis Plus公共字段自动填充(MyMetaObjectHandler)
Mybatis Plus公共字段自动填充(MyMetaObjectHandler)
905 0
|
5月前
|
缓存 Java 索引
|
5月前
|
存储 Java 索引
说一说浅析 HashMap 原理
我是小假 期待与你的下一次相遇 ~
说一说浅析 HashMap 原理
|
5月前
|
存储 Java Linux
详细地说一说零拷贝
我是小假 期待与你的下一次相遇 ~
252 1
详细地说一说零拷贝
|
5月前
|
消息中间件 缓存 固态存储
说一说 Java 中的内存映射(mmap)
我是小假 期待与你的下一次相遇 ~
179 1
说一说 Java 中的内存映射(mmap)
|
4月前
|
存储 负载均衡 算法
我们来说一说 Java 的一致性 Hash 算法
我是小假 期待与你的下一次相遇 ~
133 1
|
12月前
|
安全 Java 数据安全/隐私保护
有哪些场景不适合使用Java反射机制
Java反射机制虽强大,但并非万能。在性能要求极高、安全性严格控制、类结构复杂多变或对象创建频繁的场景下,使用反射可能带来性能下降、安全风险增加等问题,应谨慎选择。
282 11
|
5月前
|
Java Maven 微服务
说一说 Maven 使用 profile 实现多套环境变量
我是小假 期待与你的下一次相遇 ~
|
5月前
|
JSON Java 数据库连接