继承、this 与 super 关键字及访问修饰符知识点详解

一、复习回顾

  1. 数组创建方式

    • 固定长度:new int[3];(创建长度为 3 的 int 数组,元素为默认值 0)
    • 直接赋值:new int[]{1, 3, 5};(创建并初始化数组)
    • 存值操作:arr[0] = 10;(通过下标赋值)
  2. 构造方法

    • 核心作用:初始化对象(为对象分配内存并设置初始状态)
    • 无参构造:public Person(){}(属性为默认值,如 int 为 0,String 为 null)
    • 有参构造:public Person(String name){this.name=name;}(属性为指定值)
  3. 对象创建过程

    Person p = new Person(); 
    // 执行步骤:
    // 1. 分配内存空间
    // 2. 属性默认初始化(name=null, age=0)
    // 3. 执行构造方法内代码(若有)
    
  4. this 关键字基础用法

    • 区分成员变量与局部变量:this.name = name;
    • 调用本类方法:this.eat();
    • 调用本类构造:this("张三");(必须在构造方法第一行)
  5. 重载 (Overload) 示例

    // 方法名相同,参数列表不同(个数/类型/顺序)
    public void sum(int a, int b){}
    public void sum(double a, double b){} // 重载
    public void sum(int a, double b){}    // 重载
    
  6. 类封装完整示例

    public class Student {
        // 1. 属性私有
        private String name;
        
        // 2. 提供set/get方法
        public void setName(String name) {
            // 可添加验证逻辑
            if(name != null) {
                this.name = name;
            }
        }
        public String getName() {
            return name;
        }
    }
    

二、继承(重点)

2.1 继承概念与语法

  • 核心价值:代码复用(提取共性)+ 多态基础
  • 语法子类 extends 父类(Java 仅支持单继承)
  • 示例
    // 父类(基类)
    class Animal {
        String name;
        void eat() {
            System.out.println("动物进食");
        }
    }
    
    // 子类(派生类)
    class Dog extends Animal {
        // 自动拥有name属性和eat()方法
        void bark() {
            System.out.println(name + "汪汪叫");
        }
    }
    
    // 测试
    public class Test {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.name = "大黄"; // 使用父类属性
            dog.eat();        // 调用父类方法
            dog.bark();       // 调用子类方法
        }
    }
    

2.2 继承中的属性访问

  1. 访问规则

    • 父类非私有属性:子类可直接访问
    • 父类私有属性:需通过父类的 set/get 方法访问
    • 同名属性:子类默认访问自身属性,父类属性需用super
  2. 示例

     
    class Father {
        String name = "父亲";
        private int money = 10000; // 私有属性
        
        public int getMoney() { return money; }
    }
    
    class Son extends Father {
        String name = "儿子"; // 与父类同名
        
        public void show() {
            System.out.println(name);       // 儿子(自身属性)
            System.out.println(super.name); // 父亲(父类属性)
            System.out.println(getMoney()); // 10000(通过方法访问私有属性)
        }
    }
    

2.3 继承中的方法访问

  1. 访问规则

    • 父类非私有方法:子类可直接调用
    • 父类私有方法:子类无法访问
    • 同名方法:子类默认调用自身方法(重写)
  2. 示例

    class Father {
        public void work() {
            System.out.println("父亲工作");
        }
        private void sleep() {
            System.out.println("父亲睡觉");
        }
    }
    
    class Son extends Father {
        public void work() { // 重写父类方法
            System.out.println("儿子工作");
        }
        
        public void test() {
            work();       // 儿子工作(自身方法)
            super.work(); // 父亲工作(父类方法)
            // sleep();   // 错误:无法访问私有方法
        }
    }
    

2.4 继承中的构造方法

  1. 执行顺序:创建子类对象时,先执行父类构造,再执行子类构造

  2. 默认规则:子类构造中隐含super()(调用父类无参构造)

  3. 显式调用:使用super(参数)调用父类有参构造(必须在第一行,此时默认调用的父类无参构造就不生效了)

  4. 示例

    class Father {
        public Father() {
            System.out.println("父类无参构造");
        }
        public Father(String name) {
            System.out.println("父类有参构造:" + name);
        }
    }
    
    class Son extends Father {
        public Son() {
            // super(); // 隐含调用父类无参构造
            System.out.println("子类无参构造");
        }
        
        public Son(String name) {
            super(name); // 显式调用父类有参构造
            System.out.println("子类有参构造");
        }
    }
    
    // 测试
    public class Test {
        public static void main(String[] args) {
            new Son(); 
            // 输出:父类无参构造 → 子类无参构造
            
            new Son("张三"); 
            // 输出:父类有参构造:张三 → 子类有参构造
        }
    }
    

三、重写 (Override)

3.1 重写规则

  • 方法名、参数列表、返回值类型必须完全一致
  • 访问修饰符不能严于父类(如父类public,子类不能是private
  • @Override注解标识(可选,但推荐,编译器会校验)

3.2 示例

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

class Bird extends Animal {
    @Override // 标识重写
    public void move() { // 完全匹配父类方法签名
        System.out.println("鸟飞翔");
    }
}

class Fish extends Animal {
    @Override
    public void move() {
        System.out.println("鱼游动");
    }
}

3.3 重写与重载的区别

特性重写 (Override)重载 (Overload)
发生位置父子类之间同一类中
方法名必须相同必须相同
参数列表必须相同必须不同
返回值必须相同可不同
访问修饰符不能严于父类无限制

四、this 与 super 对比

功能this 用法super 用法
访问属性this.name(当前对象属性)super.name(父类对象属性)
调用方法this.eat()(当前类方法)super.eat()(父类方法)
调用构造方法this()/this(参数)super()/super(参数)
代表对象当前类的实例对象父类的实例对象(在子类中使用)
使用位置本类的方法 / 构造中子类的方法 / 构造中

示例:this 与 super 综合使用

class Person {
    String name;
    public Person(String name) {
        this.name = name;
    }
    public void say() {
        System.out.println("我是" + name);
    }
}

class Student extends Person {
    String name; // 子类自己的name
    public Student(String pName, String sName) {
        super(pName); // 调用父类构造
        this.name = sName; // 区分子类属性
    }
    @Override
    public void say() {
        super.say(); // 调用父类方法
        System.out.println("我叫" + this.name); // 调用子类属性
    }
}

// 测试
public class Test {
    public static void main(String[] args) {
        Student s = new Student("王大明", "王小明");
        s.say(); 
        // 输出:
        // 我是王大明(父类方法)
        // 我叫王小明(子类方法)
    }
}

五、访问修饰符

修饰符当前类当前包其他类其他包子类其他包非子类
public✔️✔️✔️✔️
protected✔️✔️✔️
缺省(默认)✔️✔️
private✔️

示例:访问修饰符效果

// 包1: com.a
package com.a;
public class Father {
    public int a = 1;
    protected int b = 2;
    int c = 3; // 缺省
    private int d = 4;
    
    public void test() {
        // 当前类中都可访问
        System.out.println(a + b + c + d); 
    }
}

// 包1中的其他类
package com.a;
public class OtherInSamePackage {
    public void access(Father f) {
        System.out.println(f.a); // 
        System.out.println(f.b); // 
        System.out.println(f.c); // 
        // System.out.println(f.d); //  private不可访问
    }
}

// 包2中的子类
package com.b;
import com.a.Father;
public class Son extends Father {
    public void access() {
        System.out.println(a); // 
        System.out.println(b); // 
        // System.out.println(c); //  缺省在其他包不可访问
        // System.out.println(d); //  private不可访问
    }
}

// 包2中的非子类
package com.b;
import com.a.Father;
public class OtherInOtherPackage {
    public void access(Father f) {
        System.out.println(f.a); // 
        // System.out.println(f.b); //  protected在其他包非子类不可访问
        // System.out.println(f.c); // 
        // System.out.println(f.d); // 
    }
}

六、常见问题与解决

  1. 空指针异常:当对象为null时调用方法 / 属性

    Student[] students = new Student[3];
    // students[0] 为 null,直接调用会报错
    students[0].getName(); // 空指针异常
    // 解决:先初始化数组元素
    students[0] = new Student(); 
    
  2. 父类无无参构造:子类必须显式调用父类有参构造

    class Father {
        public Father(String name) {} // 只有有参构造
    }
    
    class Son extends Father {
        public Son() {
            super("默认名"); // 必须显式调用,否则编译错误
        }
    }
    
  3. 重写与静态方法:静态方法不能被重写(属于类,不属于实例)

    class Father {
        public static void test() {}
    }
    
    class Son extends Father {
        // 这是子类自己的静态方法,不是重写
        public static void test() {} 
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值