知识框架
super 概述(理解)
super 和 this 可以对比着学习:
this
- this 是一个引用,保存内存地址指向自己。
- this 出现在实例方法中,谁调用这个实例方法,this 就代表谁,this 代表当前正在执行这个动作的对象。
- this 不能出现在静态方法中。
- this 大部分情况下可以省略,在方法中区分实例变量和局部变量的时候不能省略。
- “this(实际参数列表)”出现在构造方法第一行,通过当前的构造方法去调用本类当中其它的构造方法。
super
- super能出现在实例方法和构造方法中。
- super的语法是:“super.”、“super()”
- super不能使用在静态方法中。
- super. 大部分情况下是可以省略的。
- super.什么时候不能省略呢? ???????
- super() 只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中的构造方法,目的是:创建子类对象的时候,先初始化父类型特征。
- super()表示通过子类的构造方法调用父类的构造方法。模拟现实世界中的这种场景:要想有儿子,需要先有父亲。
重要的结论:
当一个构造方法第一行:既没有this()又没有super()的话,默认会有一个super();表示通过当前子类的构造方法调用父类的无参数构造方法。所以必须保证父类的无参数构造方法是存在的。 注意:this()和super() 不能共存,它们都是只能出现在构造方法第一行。- 无论是怎样折腾,父类的构造方法是一定会执行的。
- 在构造方法执行过程中一连串调用了父类的构造方法,父类的构造方法又继续向下调用它的父类的构造方法,但是实际上对象只创建了一个。
三种用法
this和super的区别
继承中构造方法的访问特点
- 子类中所有的构造方法默认都会访问父类中无参的构造方法
- 子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认都是:super()
- 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的
- 对象在堆内存中,会单独存在一块super区域,用来存放父类的数据
问题:如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢?
- 通过使用super关键字去显示的调用父类的带参构造方法
- 在父类中自己提供一个无参构造方法
关键字final
final 表示不可改变的含义
- 采用 final 修饰的类不能被继承
- 采用 final 修饰的方法不能被覆盖
- 采用 final 修饰的变量不能被修改
- final 修饰的变量必须显示初始化如果修饰的引用,那么这个引用只能指向一个对象,也就是说这个引用不能再次赋值,但被指向的对象是可以修改的
构造方法不能被 final 修饰会影响 JAVA类的初始化:final 定义的静态常量调用时不会执行 java 的类初始化方法,也就是说不会执行 static 代码块等相关语句,这是由 java 虚拟机规定的。我们不需要了解的很深,有个概念就可以了。final修饰的实例变量一般和static联合使用,称为常量。public static final double PI = 3.1415926;
采用 final 修饰的类不能被继承
格式:
- 含义:当前这个类不能有任何的子类。(太监类)
- 注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子。)
package cn.itcast.day11.demo01; /* 当final关键字用来修饰一个类的时候,格式: public final class 类名称 { // ... } */ public final class MyClass /*extends Object*/ { public void method() { System.out.println("方法执行!"); } }
采用 final 修饰的方法不能被覆盖
格式:
- 含义:当final关键字用来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写。
- 注意:对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。
class A1 { public final void test1() { } }
final修饰局部变量
- 基本类型不能被修改
public class PackTest { public static void main(String[] args) { // 声明变量,使用final修饰 final int a; // 第一次赋值 a = 10; // 第二次赋值 a = 20; // 报错,不可重新赋值 // 声明变量,直接赋值,使用final修饰 final int b = 10; // 第二次赋值 b = 20; // 报错,不可重新赋值 } }
final修饰局部变量
- 引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改,代码如下:
public class PackTest { public static void main(String[] args) { // 创建 User 对象 final User u = new User(); // 创建 另一个 User对象u = new User(); // 报错,指向了新的对象,地址值改变。 // 调用setName方法 u.setName("张三"); // 可以修改 } }
final修饰成员变量
对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变。
- 由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值了。
- 对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。二者选其一。
- 必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。
显示初始化:
public class PackTest { final String USERNAME = "张三"; private int age; }
构造方法初始化:
public class PackTest { final String USERNAME; private int age; public PackTest(String username, int age) { this.USERNAME = username; this.age = age; } }