目录
1、继承
1.1概念
继承是 面向对象的三大特征之一,java 的继承的出现是来提高代码的复用性,
继承的类是子类(派生类),被继承的类是父类(基类、派生类)
继承的关系 是 is-a 的关系 例如: 狗 is a 动物;主要是进行对共性的提取,实现代码的复用
语法:
public class 子类名 extends 父类名{
}
子类继承了父类的成员变量和成员方法,同时也可以在类中追加定义自己的属性和方法
class Animal{
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(name + "吃东西");
}
}
class Dog extends Animal{
public Dog(String name, int age) {
//子类构造 需要先实现 父类构造
super(name, age);
}
//特有方法
public void wangwang(){
System.out.println(name + "旺旺叫");
}
}
class Cat extends Animal{
public Cat(String name, int age) {
super(name, age);
}
//特有方法
public void miaomiao(){
System.out.println(name + "喵喵叫");
}
}
1.2 子类访问父类
1、 父类成员变量访问
子类 访问 父类成员变量(public):
- 子类中 有同名同类型,优先子类;自己独有,直接访问自己
- 子类中 有同名不同类型,判断类型访问
- 子类中 无,访问继承父类的成员变量,如果没有,编译报错
成员变量访问 遵循就近原则,自己有就优先自己,无就去父类找
如果是父类私有成员变量,被继承,但不能使用
2、父类成员方法访问
子类 访问 父类成员方法:
- 子类 访问 不同名称的方法,优先在自己类中寻找,否则去父类寻找,找到访问,无则编译错误
- 子类 访问 相同名称的方法,如果父类和子类 同方法名的参数列表不同(重载),根据参数列表匹配访问; 同方法名的参数列表相同就是重写,优先子类中方法,子类中没有就去使用父类中方法,无则编译错误
1.3 子类 构造
子类对象中成员是有两部分组成的,父类继承下来的以及子类新增加的部分。
先有父类,再有子类;所以子类构造是 也是首先去调用父类构造,构造完父类成员变量,再调用子类的构造方法,将子类自有的成员变量初始化完成。
class Animal{
public String name;
public int age;
public Animal(){
System.out.println("Animal无参构造");
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Animal 2个参构造");
}
public void eat(){
System.out.println(name + "吃东西");
}
}
class Dog extends Animal{
public String move;
public Dog(){
//隐藏
//super();
System.out.println("Dog无参构造");
}
public Dog(String name, int age,String move) {
//子类构造 需要先实现 父类构造
super(name, age);
this.move = move;
System.out.println("Dog有参构造");
}
//特有方法
public void wangwang(){
System.out.println(name + "旺旺叫");
}
}
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println("============");
Dog dog2 = new Dog("小花",3);
}
子类的构造方法中第一行 都会默认有一条隐藏语句: super();
- 子类有参构造中不写指定父类的有参构造,只会自动调用父类无参构造;
- 如果父类中定义的有参构造,但是没有写无参构造,系统不会自动生成无参,编译报错;
- 构造方法中,super() 只能被写再第一行,只能出现一次,且不能与this()同时出现,因为两者一个调用父类,一个调用自己,都只能写在第一行,出现冲突;
2、 super 关键字
super 关键字 ,作用是再写代码或读代码是提高可读性
在对象实例化时,对象内 不包括super,但是包括this(隐藏)
super 只能指代 直接的父类
- super.data 在子类中 访问父类的成员变量
- super.func() 在子类中 访问父类的成员方法
- 只能在 非静态方法中使用,静态是属于类的,可以不实例化,super代表父类的引用,而在静态方法中,由于没有实例化对象,所以也就没有父类对象可以调用了。
super 和 this 的异同
相同点:
- 都是 java 中的关键字
- 只能在类的非静态方法中调用,用来访问 非静态成员变量和方法
- 在构造方法中调用时,必须是构造方法的第一条语句,并且不能同时存在
不同点:
- this 是当前对象的引用,实例化时就指代当前对象;super 相当于时子类对象中从父类继承下来的部分成员的引用(代表当前对象内部的那一块父类特征)
- 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
- 在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现
- 子类构造方法中一定会存在super(...)的调用(默认),用户没有写编译器也会增加,但是this(...)用户不写则没有
3、代码块 初始化
代码块:实例代码块 和 静态代码块
在继承关系时,它们的执行顺序是怎样?
- 静态代码块 先执行,只执行一次,在类加载时执行;子类继承父类,先执行父类的静态代码块,再执行自己的静态代码块
- 之后时 实例代码块,子类构造时要先帮父类构造,所以 父类实例代码块、父类构造代码先执行,再执行 子类的 实例代码块 和 构造代码;
顺序:
- 父类静态代码块 -> 子类静态代码块(静态)->
- ->父类实例代码块 -> 父类构造代码 (父类)->
- ->子类实例代码块 -> 子类构造代码 (子类)
- 第二次执行实例化,父类 和 子类的静态代码就不会再执行
4、修饰限定符
范围 | private | default | protected | public |
同一包中的同一类 | ✓ | ✓ | ✓ | ✓ |
同一包中的不同类 | ✓ | ✓ | ✓ | |
不同包中的子类 | ✓ | ✓ | ||
不同包中的非子类 | ✓ |
private:私有的,被其修饰的类、属性、方法,只能被该类的对象访问;
default:默认的,只允许 同一个包下的类 访问;
protected:受保护的,被其修饰的类、属性、方法,只能被该类的对象和继承该类的子类访问;
public:公共的,被其修饰的类、属性、方法,可以被其他类的对象访问,也可挎包访问;
5、继承的方式
6、final 关键字
1.final 变量:当一个变量被声明为 final 时,它的值不能被修改。这意味着一旦给 final 变量赋了一个值,就不能再更改它的值
final int x = 10;
// x = 20; // 编译错误,无法修改 final 变量的值
2.final 方法:当一个方法被声明为 final 时,子类无法重写该方法。这通常用于确保方法的实现不能被修改
public class Parent {
public final void display() {
System.out.println("Parent's display method");
}
}
public class Child extends Parent {
// 无法重写 display 方法
}
3. final 类:当一个类被声明为 final 时,该类不能被继承。这样做是为了防止类的修改和派生类的创建。
public final class FinalClass {
// 类的实现
}
// 无法创建 FinalClass 的子类
4. final 参数:当一个方法的参数被声明为 final 时,表示参数在方法内部不能被修改。这主要用于传递不可变的参数给方法。
public void process(final int x) {
// x = 10; // 编译错误,无法修改 final 参数的值
}