继承与 this 关键字

一、数组进阶巩固

  1. 数组创建方式

    • new int[3];(指定长度)
    • new int[]{值1, 值2, ...};(直接初始化,长度固定)
    • 存值:数组名[下标] = 值
  2. 构造方法

    • 作用:创建对象并初始化属性
    • 无参构造:创建的对象属性为默认值
    • 有参构造:创建的对象属性为指定值
  3. 对象创建过程

    • new 关键字调用构造方法
    • 先执行属性初始化,再执行构造方法内代码
  4. this 关键字

    • 指代当前类的对象
    • 用法:this.属性this.方法()this()(调用本类无参构造)、this(参数)(调用本类有参构造)
  5. 方法重载(Overload)

    • 方法名相同,参数列表不同(参数个数 / 类型 / 顺序)(方法重载是在同一个类中)
    • 与返回值类型无关
  6. 类的封装步骤

    • 属性用 private 修饰,使得类外不能通过对象直接调属性
    • 提供 setter 和 getter 方法
  7. 示例代码

public class Square{
    int l;
    public Square(){
        this(1); // 调用本类有参构造
    }
    public Square(int l){
        this.l = l; // this区分成员变量和局部变量
    }
}

二、案例展示

3. 老师与学生类设计

学生类(Student)
package com.qf.homework;

public class Student {
    private int age;
    private String name;

    // 无参构造
    public Student() {}

    // 有参构造
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }

    // getter/setter方法
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}
老师类(Teacher)
package com.qf.homework;

public class Teacher {
    private int age;
    private String name;
    private Student[] stuArr; // 存储学生的数组

    // 构造方法
    public Teacher() {}
    public Teacher(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public Teacher(int age, String name, Student[] stuArr) {
        this.age = age;
        this.name = name;
        this.stuArr = stuArr;
    }

    // getter/setter方法
    public Student[] getStuArr() { return stuArr; }
    public void setStuArr(Student[] stuArr) { this.stuArr = stuArr; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}
空指针异常演示
// 演示空指针异常场景
public static void test() {
    Teacher teacher = new Teacher(40, "老王");
    
    // 场景1:数组未初始化(stuArr为null)
    // Student[] stuArr1 = teacher.getStuArr();
    // stuArr1[0].getAge(); // 空指针异常
    
    // 场景2:数组初始化但元素未实例化
    Student[] stuArr = new Student[3];
    teacher.setStuArr(stuArr);
    Student[] stuArr2 = teacher.getStuArr();
    // stuArr2[0].getAge(); // 空指针异常(数组元素为null)
}
老师存储学生数组测试
package com.qf.a_homework;

class Teacher {
    private String t_name;
    private int t_age;
    private Student[] students;

    // getter/setter方法
    public String getT_name() { return t_name; }
    public void setT_name(String t_name) { this.t_name = t_name; }
    public int getT_age() { return t_age; }
    public void setT_age(int t_age) { this.t_age = t_age; }
    public Student[] getStudents() { return students; }
    public void setStudents(Student[] students) { this.students = students; }
}

class Student {
    private String s_name;
    private int s_age;

    public Student(String s_name, int s_age) {
        this.s_name = s_name;
        this.s_age = s_age;
    }

    // getter/setter方法
    public String getS_name() { return s_name; }
    public void setS_name(String s_name) { this.s_name = s_name; }
    public int getS_age() { return s_age; }
    public void setS_age(int s_age) { this.s_age = s_age; }
}

public class Demo1 {
    public static void main(String[] args) {
        Teacher t = new Teacher();
        t.setT_name("老任");
        t.setT_age(37);
        
        // 初始化学生数组并赋值
        Student[] stus = new Student[3];
        stus[0] = new Student("小赵", 18);
        stus[1] = new Student("小原", 19);
        stus[2] = new Student("小王", 20);
        t.setStudents(stus);
        
        // 输出信息
        System.out.println(t.getT_name());
        System.out.println(t.getT_age());
        for (int i = 0; i < stus.length; i++) {
            System.out.println(stus[i].getS_name() + "-----" + stus[i].getS_age());
        }
    }
}
复数类(Complex)
package com.qf.b_home;

class Complex {
    double real; // 实部
    double im;   // 虚部

    public Complex() {}
    public Complex(double real, double im) {
        this.real = real;
        this.im = im;
    }

    // 复数加法
    public Complex add(Complex c) {
        return new Complex(this.real + c.real, this.im + c.im);
    }
    
    // 复数减法(未实现)
    public void sub() {}
    
    // 复数乘法(未实现)
    public void mul() {}
}

public class Demo2 {
    public static void main(String[] args) {
        Complex c1 = new Complex(1.5, -3); // 1.5 - 3i
        Complex c2 = new Complex(2.3, 2.4); // 2.3 + 2.4i
        Complex c3 = c1.add(c2);
        System.out.println(c3.real + " + " + c3.im + "i"); // 3.8 + (-0.6)i
    }
}

三、继承(重点)

2.1 继承的概念

  • 面向对象三大特性:封装、继承、多态
  • 生活中的继承:子类继承父类的财产
  • 代码中的继承:子类继承父类的属性和方法,实现代码复用
  • 语法public class 子类 extends 父类 {}
  • 特点:Java 中只能单继承(一个类只能有一个直接父类)

2.2 入门案例

package com.qf.c_extends;

class Father {
    String name;
    int age;
}

// 子类继承父类
class Son extends Father {}

public class Demo1 {
    public static void main(String[] args) {
        Son son = new Son();
        son.name = "小王";
        son.age = 18;
        System.out.println(son.name + son.age);
    }
}

2.3 继承中的属性

  1. 子类可以使用父类的非私有属性
  2. 父类私有属性(private)子类无法直接访问,需通过父类的公共方法访问
  3. 子类与父类有同名属性时,子类默认使用自己的属性(就近原则)
package com.qf.c_extends;

class Father {
    String name = "爸爸";
    int age;
    private int money; // 私有属性

    public int getMoney() { return money; }
    public void setMoney(int money) { this.money = money; }
}

class Son extends Father {
    String name = "儿子"; // 与父类同名属性
}

public class Demo1 {
    public static void main(String[] args) {
        Son son = new Son();
        son.age = 18;
        son.setMoney(100); // 通过父类方法访问私有属性
        System.out.println(son.name + son.age + son.getMoney()); // 输出:儿子18100
    }
}

2.4 继承中的方法

  1. 子类可以使用父类的非私有方法
  2. 父类私有方法(private)子类无法访问
  3. 子类与父类有同名方法(参数列表相同)时,默认调用子类的方法(重写
package com.qf.c_extends;

class Father {
    public void eat() {
        System.out.println("father吃饭");
    }
    private void sleep() { // 私有方法
        System.out.println("father睡觉");
    }
}

class Son extends Father {
    public void eat() { // 重写父类方法
        System.out.println("son吃饭");
    }
}

public class Demo1 {
    public static void main(String[] args) {
        Son son = new Son();
        son.eat(); // 调用子类重写的方法
        // son.sleep(); // 无法访问父类私有方法
    }
}

2.5 继承中的构造方法

  • 创建子类对象时,会先调用父类的构造方法(先有父再有子)
  • 子类构造方法中默认隐含 super()(调用父类无参构造)
  • super() 必须放在子类构造方法的第一行
package com.qf.d_extends;

class Father {
    public Father() {
        System.out.println("father无参构造");
    }
}

class Son extends Father {
    public Son() {
        // super(); // 默认存在,调用父类无参构造
        System.out.println("son无参构造");
    }
}

public class Demo1 {
    public static void main(String[] args) {
        Son son = new Son(); 
        // 输出顺序:father无参构造 → son无参构造
    }
}

四、重写(Override)

概念

  • 发生在父子类之间,子类重写父类的方法
  • 当父类方法不满足子类需求时使用

重写规则

  1. 方法名、参数列表、返回值类型必须与父类一致
  2. 访问修饰符权限不能小于父类
  3. 可用 @Override 注解标识(增强可读性,编译器校验)

示例

package com.qf.e_overide;

class Animal {
    public void eat() {
        System.out.println("动物吃");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头"); // 重写父类方法
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼"); // 重写父类方法
    }
}

public class Demo2 {
    public static void main(String[] args) {
        Dog d1 = new Dog();
        d1.eat(); // 输出:狗吃骨头
        Cat c1 = new Cat();
        c1.eat(); // 输出:猫吃鱼
    }
}

五、this 与 super 的区别

用途this(当前对象)super(父类对象)
调用属性this.属性(优先本类,再父类)super.属性(直接访问父类)
调用方法this.方法()(优先本类,再父类)super.方法()(直接访问父类)
调用构造this()/this(参数)(本类构造)super()/super(参数)(父类构造)

注意事项

  • 调用构造方法的语句必须放在构造方法内,且位于第一行
  • super 只能在子类中使用

示例

package com.qf.f_super;

class Father {
    String name = "张三";
    public void eat() {
        System.out.println("father吃饭");
    }
}

class Son extends Father {
    String name = "张四";
    
    public Son() {
        super(); // 调用父类构造
        System.out.println(super.name); // 访问父类属性
    }
    
    @Override
    public void eat() {
        System.out.println("son吃饭");
    }
    
    public void show() {
        System.out.println(name); // 本类属性
        System.out.println(this.name); // 本类属性
        System.out.println(super.name); // 父类属性
        super.eat(); // 父类方法
        this.eat(); // 本类方法
    }
}

public class Demo1 {
    public static void main(String[] args) {
        Son son = new Son();
        son.show();
    }
}

六、访问修饰符

修饰符当前类当前包其他类其他包子类其他包非子类
public
protected×
缺省(默认)××
private×××
  • 作用:限制类、属性、方法、构造方法的访问权限
  • 常用场景:属性通常用 private,方法用 public 或 protected
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值