Skip to content

Java面向对象核心:JavaBean、对象数组与继承完全指南 ​

目录 ​


一、JavaBean详解 ​

1.1 JavaBean的作用 ​

核心作用:封装数据

JavaBean主要用于封装数据,即将数据赋值给JavaBean中的属性。在实际开发中,JavaBean类都与数据库表对应。

1.2 JavaBean与数据库表的对应关系 ​

数据库JavaBean
表名类名
列名属性名
列的类型属性的数据类型
每一行数据JavaBean的对象

示例:

java
// 数据库表:user
// 列:id, username, password

public class User {
    private int id;
    private String username;
    private String password;
    
    // 构造方法
    public User() {}
    
    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
    
    // getter/setter方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
}

1.3 JavaBean在开发中的实际应用 ​

应用场景一:添加功能 ​

在添加功能中,JavaBean用于封装页面上发送过来的数据,一层一层传递到DAO层,在DAO层中调用JavaBean对象中的getXXX方法,将属性值获取出来,放到SQL语句中。

流程:

页面数据 → JavaBean封装 → Service层 → DAO层 → 数据库

应用场景二:查询功能 ​

在查询功能中,JavaBean用于封装从数据库中查询出来的数据,然后一层一层返回给页面上进行展示。

流程:

数据库查询结果 → JavaBean封装 → Service层 → 页面展示

1.4 标准JavaBean的组成 ​

一个标准的JavaBean应该包含:

  1. 私有属性:使用private修饰
  2. 无参构造方法:必须提供
  3. 有参构造方法:可选,建议提供
  4. getter/setter方法:为每个属性提供访问方法

快速生成: 使用IDE快捷键 Alt + Insert (Windows) 或 Cmd + N (Mac)


二、对象数组 ​

2.1 概念 ​

对象数组是指数组中存储的元素是对象类型的数据。

定义格式:

java
// 数据类型[] 数组名 = new 数据类型[长度];
Person[] arr = new Person[3];

2.2 实战示例 ​

需求: 定义一个数组,存3个Person对象,遍历数组,将Person对象中的属性值获取出来

Person类:

java
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

测试类:

java
public class Test01 {
    public static void main(String[] args) {
        // 1.定义存储Person对象的数组
        Person[] arr1 = new Person[3];
        
        // 2.创建三个Person对象
        Person p1 = new Person("小王", 10);
        Person p2 = new Person("小张", 20);
        Person p3 = new Person("小李", 30);
        
        // 3.将三个对象放到数组中
        arr1[0] = p1;
        arr1[1] = p2;
        arr1[2] = p3;

        // 4.遍历数组
        for (int i = 0; i < arr1.length; i++) {
            Person p = arr1[i];
            System.out.println(p.getName() + "..." + p.getAge());
        }
    }
}

2.3 对象数组的内存图解 ​

对象数组在内存中的存储结构:

  • 数组存储的是对象的引用(地址值)
  • 实际的对象存储在堆内存中
  • 通过数组索引可以访问到具体的对象

三、继承核心概念 ​

3.1 什么是继承 ​

面向对象三大特征: 封装、继承、多态

继承的定义: 多个类中有相同的成员,我们定义一个父类,将相同的成员抽取到父类中,子类直接继承父类,然后直接使用父类抽取出来的成员。

格式:

java
class 子类 extends 父类 {
    // 子类特有的成员
}

3.2 继承的注意事项 ​

注意点说明
私有成员子类可以继承父类中私有和非私有成员,但不能直接使用私有成员
构造方法构造方法不能继承
静态方法静态方法可以继承但不能被重写

3.3 继承的使用示例 ​

父类:

java
public class Employee {
    String name;
    int age;

    public void work() {
        System.out.println("员工正在工作...");
    }
    
    private void eat(){
        System.out.println("员工正在吃...");
    }
}

子类:

java
public class Teacher extends Employee {
    // Teacher类自动拥有name、age属性和work()方法
}

public class Manager extends Employee {
    // Manager类自动拥有name、age属性和work()方法
}

测试类:

java
public class Test01 {
    public static void main(String[] args) {
        Teacher t1 = new Teacher();
        t1.name = "涛哥";
        t1.age = 16;
        System.out.println(t1.name + "..." + t1.age);
        t1.work();
        // t1.eat(); // 错误:不能直接使用父类中私有成员

        System.out.println("======================");
        Manager m1 = new Manager();
        m1.name = "许姐";
        m1.age = 18;
        System.out.println(m1.name + "..." + m1.age);
        m1.work();
    }
}

3.4 继承中成员变量的访问特点 ​

情况一:成员变量不重名 ​

java
public class Fu {
    public int numFu = 100;
}

public class Zi extends Fu {
    public int numZi = 10;
}

// 测试
Fu fu = new Fu();
System.out.println(fu.numFu); // 100

Zi zi = new Zi();
System.out.println(zi.numFu); // 100 (继承自父类)
System.out.println(zi.numZi); // 10 (子类自己的)

情况二:成员变量重名 ​

访问规则: 看等号左边是谁,先调用谁中的成员变量;子类没有找父类

java
public class Fu {
    public int num = 10000;
}

public class Zi extends Fu {
    public int num = 1000;
}

// 测试
Zi zi = new Zi();
System.out.println(zi.num); // 1000 (子类的)

Fu f = new Zi(); // 多态
System.out.println(f.num); // 10000 (父类的,看等号左边)

3.5 继承中成员方法的访问特点 ​

情况一:成员方法不重名 ​

java
public class Fu {
    public void numFu(){
        System.out.println("父类numFu方法");
    }
}

public class Zi extends Fu {
    public void numZi(){
        System.out.println("子类numZi方法");
    }
}

// 测试
Zi zi = new Zi();
zi.numZi(); // 子类numZi方法
zi.numFu(); // 父类numFu方法 (继承而来)

情况二:成员方法重名(方法重写) ​

访问规则: 看new的是谁,先调用谁中的成员方法;子类没有,找父类

java
public class Fu {
    public void num(){
        System.out.println("父类num方法");
    }
}

public class Zi extends Fu {
    @Override
    public void num(){
        System.out.println("子类num方法");
    }
}

// 测试
Zi zi = new Zi();
zi.num(); // 子类num方法

Fu f = new Zi(); // 多态
f.num(); // 子类num方法 (看new的是谁)

3.6 继承的特点 ​

特点说明示例
单继承一个类只能有一个直接父类class Zi extends Fu ✅
class Zi extends Fu, Ye ❌
多层继承支持多层继承体系class Zi extends Fu
class Fu extends Ye
多子类一个父类可以有多个子类class Zi extends Fu
class Bro extends Fu

3.7 继承中构造方法的特点 ​

核心特点: 创建子类对象时,先初始化父类

原因: 每一个类中的构造方法第一行默认有一个super(),不写JVM自动提供一个

super()的作用: 代表调用父类无参构造

示例:

java
public class Fu {
    public Fu(){
        System.out.println("父类无参构造方法");
    }
}

public class Zi extends Fu {
    public Zi(){
        super(); // 默认存在,调用父类无参构造
        System.out.println("子类无参构造方法");
    }

    public Zi(int num){
        super(); // 默认存在
        System.out.println("子类有参构造方法");
    }
}

// 测试
Zi zi = new Zi();
// 输出:
// 父类无参构造方法
// 子类无参构造方法

四、方法重写 ​

4.1 什么是方法重写 ​

定义: 子类中有一个和父类方法名以及参数列表都一样的方法,这个方法叫做重写的方法。

判断标准: 使用@Override注解,如果这个注解不报错就是重写的,否则就不是重写的方法。

4.2 方法重写的规则 ​

规则说明
权限修饰符子类方法重写父类方法,必须保证权限大于等于父类权限
public → protected → 默认 → private
方法签名方法名和参数列表必须一模一样
返回值类型应该是父类方法返回值类型的子类类型(一般情况下都一样)
私有方法私有方法不能被重写
构造方法构造方法不能被重写
静态方法静态方法不能被重写

4.3 方法重写示例 ​

基础示例:

java
public class Fu {
    public void num(){
        System.out.println("父类num方法");
    }
    
    public Fu method01(){
        return null;
    }
}

public class Zi extends Fu {
    @Override
    public void num(){
        System.out.println("子类num方法");
    }
    
    @Override
    public Zi method01(){
        // 返回值类型可以是父类返回值类型的子类
        return null;
    }
}

4.4 方法重写的使用场景 ​

场景: 在子类中对父类中的方法进行升级改造

实战案例:手机功能升级

java
// 旧手机
public class OldPhone {
    public void call(){
        System.out.println("打电话");
    }
    
    public void sendMessage(){
        System.out.println("发短信");
    }
    
    public void show(){
        System.out.println("显示手机号");
    }
}

// 新手机
public class NewPhone extends OldPhone {
    @Override
    public void show(){
        System.out.println("显示手机号");
        System.out.println("显示归属地");
        System.out.println("显示头像");
    }
}

// 测试
public class Test01 {
    public static void main(String[] args) {
        OldPhone oldPhone = new OldPhone();
        oldPhone.show(); // 显示手机号
        
        System.out.println("======================");
        
        NewPhone newPhone = new NewPhone();
        newPhone.show(); 
        // 显示手机号
        // 显示归属地
        // 显示头像
    }
}

五、super与this关键字 ​

5.1 super关键字 ​

概述: super代表的是父类引用

super的三种用法 ​

用法说明示例
调用父类构造只能在子类的构造中使用super() 调用父类无参构造
super(实参) 调用父类有参构造
调用父类成员变量在子类方法中使用super.成员变量名
调用父类方法在子类方法中使用super.方法名()

完整示例:

java
public class Fu {
    public int num = 100;
    
    public Fu(){
        System.out.println("父类无参构造");
    }
    
    public Fu(int num){
        System.out.println("父类有参构造");
    }
    
    public void show(){
        System.out.println("父类show方法");
    }
}

public class Zi extends Fu {
    public int num = 10;
    
    public Zi(){
        super(); // 调用父类无参构造
        System.out.println("子类无参构造");
    }
    
    public Zi(int num){
        super(10); // 调用父类有参构造
        System.out.println("子类有参构造");
    }
    
    @Override
    public void show(){
        super.show(); // 调用父类方法
        
        System.out.println(num); // 子类num: 10
        System.out.println(super.num); // 父类num: 100
        
        System.out.println("子类show方法");
    }
}

注意事项:

  • 在构造方法中,super关键字必须在第一行
  • 不能和this关键字同时出现在构造方法第一行

5.2 this关键字 ​

概述: this代表的是当前对象,哪个对象调用的this所在的方法,this就代表哪个对象

this的三种用法 ​

用法说明示例
调用当前对象的构造在本类的构造中使用this() 调用本类无参构造
this(实参) 调用本类有参构造
调用当前对象的成员变量在方法中使用this.成员变量名
调用当前对象的方法在方法中使用this.方法名()

完整示例:

java
public class Zi {
    public int num = 10;
    
    public Zi(){
        this(10); // 调用本类有参构造方法
        System.out.println("无参构造方法");
    }
    
    public Zi(int num){
        System.out.println("有参构造方法");
    }
    
    public void show(){
        int num = 100;
        System.out.println(num); // 局部变量: 100
        System.out.println(this.num); // 成员变量: 10
    }
}

注意事项:

  • 在构造方法中使用this,必须在第一行
  • 在构造方法中,不能this和super一起出现

5.3 super与this的区别 ​

对比项superthis
代表父类引用当前对象引用
访问成员变量super.变量 访问父类变量this.变量 访问本类变量
调用构造方法super() 调用父类构造this() 调用本类构造
调用方法super.方法() 调用父类方法this.方法() 调用本类方法

六、常见面试题 ​

6.1 基础面试题 ⭐ ​

问题1:什么是JavaBean?它在开发中的作用是什么? ​

答案:

JavaBean是一种标准的Java类,主要用于封装数据。它的作用包括:

  1. 封装数据:将数据以属性的形式存储在对象中
  2. 数据传递:在各层之间传递数据(页面→Service→DAO→数据库)
  3. 数据映射:与数据库表形成对应关系,一行数据对应一个JavaBean对象

标准JavaBean包含:

  • 私有属性
  • 无参构造方法
  • getter/setter方法

问题2:继承的特点有哪些? ​

答案:

Java继承有三个主要特点:

  1. 单继承:一个类只能有一个直接父类

    java
    class Zi extends Fu {} // 正确
    class Zi extends Fu, Ye {} // 错误
  2. 多层继承:支持多层继承体系

    java
    class Zi extends Fu {}
    class Fu extends Ye {}
  3. 多子类:一个父类可以有多个子类

    java
    class Zi extends Fu {}
    class Bro extends Fu {}

问题3:父类的私有成员能否被继承? ​

答案:

能继承,但不能直接访问。

  • 子类可以继承父类的私有成员(拥有该成员)
  • 但由于private修饰符的限制,子类不能直接访问
  • 需要通过父类提供的public的getter/setter方法来间接访问

问题4:构造方法能否被继承? ​

答案:

不能。

  • 构造方法不能被继承
  • 构造方法名必须与类名相同,如果继承会导致构造方法名与子类类名不一致
  • 子类可以通过super关键字调用父类的构造方法

6.2 进阶面试题 ⭐⭐ ​

问题5:什么是方法重写?和方法重载有什么区别? ​

答案:

方法重写(Override):

  • 定义:子类中有一个和父类方法名、参数列表都相同的方法
  • 发生在父子类之间
  • 是运行时多态的体现

方法重载(Overload):

  • 定义:同一个类中,方法名相同但参数列表不同的多个方法
  • 发生在同一个类中
  • 是编译时多态的体现

对比表格:

对比项方法重写方法重载
发生位置父子类之间同一个类中
方法名必须相同必须相同
参数列表必须相同必须不同
返回值类型相同或是子类类型无关
权限修饰符大于等于父类无关

问题6:方法重写需要遵循哪些规则? ​

答案:

  1. 权限修饰符:子类方法的权限必须大于等于父类方法的权限

    public → protected → 默认 → private
  2. 方法签名:方法名和参数列表必须完全一致

  3. 返回值类型:必须相同,或是父类方法返回值类型的子类类型

  4. 不能重写的方法:

    • 私有方法(private)
    • 构造方法
    • 静态方法(static)
    • final修饰的方法

问题7:创建子类对象时,构造方法的执行顺序是什么? ​

答案:

执行顺序: 父类构造 → 子类构造

原因:

  • 子类构造方法的第一行默认有super()
  • super()会调用父类的无参构造方法
  • 这样保证在创建子类对象前,先初始化父类部分

示例:

java
class Fu {
    public Fu() {
        System.out.println("父类构造");
    }
}

class Zi extends Fu {
    public Zi() {
        super(); // 默认存在
        System.out.println("子类构造");
    }
}

// 执行结果:
// 父类构造
// 子类构造

6.3 高级面试题 ⭐⭐⭐ ​

问题8:super和this关键字的区别是什么? ​

答案:

对比项superthis
概念父类引用当前对象引用
访问成员变量super.变量 访问父类变量this.变量 访问本类变量
调用构造方法super() 调用父类构造this() 调用本类构造
调用方法super.方法() 调用父类方法this.方法() 调用本类方法
使用位置子类构造方法中(第一行)本类构造方法中(第一行)
共存性不能和this同时出现在构造第一行不能和super同时出现在构造第一行

关键点:

  • super和this在构造方法中都必须在第一行
  • 两者不能同时出现在同一个构造方法中
  • super()由JVM默认提供,不写也会自动添加

问题9:继承中成员变量和成员方法的访问特点有什么不同? ​

答案:

成员变量:看等号左边

  • 编译看左边,运行看左边
  • 引用变量的类型决定了访问哪个成员变量
java
Fu f = new Zi();
System.out.println(f.num); // 访问父类的num

成员方法:看new的是谁

  • 编译看左边,运行看右边
  • 实际对象类型决定了调用哪个方法(动态绑定)
java
Fu f = new Zi();
f.show(); // 调用子类重写的show方法

原因: 方法重写是运行时多态,而成员变量不具备多态性。


问题10:如何为父类中private的成员变量赋值? ​

答案:

有两种方式:

方式一:使用setter方法

java
public class Employee {
    private String name;
    private int age;
    
    // setter方法
    public void setName(String name) { this.name = name; }
    public void setAge(int age) { this.age = age; }
}

public class Teacher extends Employee {}

// 使用
Teacher t = new Teacher();
t.setName("涛哥");
t.setAge(16);

方式二:使用构造方法

java
public class Employee {
    private String name;
    private int age;
    
    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class Teacher extends Employee {
    public Teacher(String name, int age) {
        super(name, age); // 调用父类有参构造
    }
}

// 使用
Teacher t = new Teacher("涛哥", 16);

七、经典练习题 ​

7.1 基础练习题 ​

练习1:学生对象数组排序 ​

题目: 定义一个学生类,声明姓名、年龄、分数,创建5个学生对象为属性赋值,放数组中,然后按照分数排序。

参考代码:

java
public class Student {
    private String name;
    private int age;
    private double score;

    public Student() {
    }

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + ", score=" + score + "}";
    }
}

public class Test {
    public static void main(String[] args) {
        // 创建5个学生对象
        Student[] students = new Student[5];
        students[0] = new Student("张三", 18, 85.5);
        students[1] = new Student("李四", 19, 92.0);
        students[2] = new Student("王五", 18, 78.5);
        students[3] = new Student("赵六", 20, 88.0);
        students[4] = new Student("钱七", 19, 95.5);

        // 按分数排序(冒泡排序)
        for (int i = 0; i < students.length - 1; i++) {
            for (int j = 0; j < students.length - 1 - i; j++) {
                if (students[j].getScore() < students[j + 1].getScore()) {
                    Student temp = students[j];
                    students[j] = students[j + 1];
                    students[j + 1] = temp;
                }
            }
        }

        // 输出排序结果
        System.out.println("按分数降序排序:");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

7.2 进阶练习题 ​

练习2:继承与重写综合练习 ​

题目:

  1. 定义一个动物类(Animal),包含name属性和eat()方法
  2. 定义猫类(Cat)和狗类(Dog)继承Animal
  3. 重写eat()方法,输出不同的内容
  4. 在测试类中创建对象并测试

参考代码:

java
// 父类
public class Animal {
    private String name;

    public Animal() {
    }

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void eat() {
        System.out.println(name + "在吃东西");
    }
}

// 子类:猫
public class Cat extends Animal {
    public Cat() {
    }

    public Cat(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println(getName() + "在吃鱼");
    }

    public void catchMouse() {
        System.out.println(getName() + "在抓老鼠");
    }
}

// 子类:狗
public class Dog extends Animal {
    public Dog() {
    }

    public Dog(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println(getName() + "在吃骨头");
    }

    public void lookHome() {
        System.out.println(getName() + "在看家");
    }
}

// 测试类
public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat("小花");
        cat.eat(); // 小花在吃鱼
        cat.catchMouse(); // 小花在抓老鼠

        Dog dog = new Dog("大黄");
        dog.eat(); // 大黄在吃骨头
        dog.lookHome(); // 大黄在看家

        // 多态
        Animal a1 = new Cat("小黑");
        a1.eat(); // 小黑在吃鱼

        Animal a2 = new Dog("小白");
        a2.eat(); // 小白在吃骨头
    }
}

八、学习建议 ​

8.1 学习重点 ​

  1. JavaBean标准结构

    • 必须掌握标准JavaBean的编写规范
    • 理解JavaBean在开发中的数据传递作用
    • 熟练使用IDE快速生成getter/setter方法
  2. 继承的核心概念

    • 理解继承的设计理念:代码复用
    • 掌握继承的使用场景和注意事项
    • 理解继承中成员访问的特点
  3. 方法重写

    • 掌握方法重写的规则
    • 理解方法重写的使用场景
    • 能够正确使用@Override注解
  4. super和this关键字

    • 理解两者的区别和用途
    • 掌握在构造方法中的使用规则
    • 理解继承中构造方法的执行顺序

8.2 常见错误 ​

  1. 忘记无参构造

    • 错误:写了有参构造,忘记写无参构造
    • 后果:子类无法调用super()
    • 解决:建议手动提供无参构造
  2. 权限修饰符错误

    • 错误:重写方法权限小于父类
    • 后果:编译错误
    • 解决:保证子类方法权限 >= 父类方法权限
  3. super和this位置错误

    • 错误:super()或this()不在构造方法第一行
    • 后果:编译错误
    • 解决:必须在构造方法第一行
  4. 混淆重写和重载

    • 错误:参数列表不一致,以为是重写
    • 后果:实际是重载,不是重写
    • 解决:使用@Override注解验证

8.3 学习路径 ​

Day 08 学习路径:
1. JavaBean(数据封装)
   ↓
2. 对象数组(对象集合)
   ↓
3. 继承基础(代码复用)
   ↓
4. 方法重写(功能扩展)
   ↓
5. super和this(引用控制)

8.4 实践建议 ​

  1. 多写代码

    • 每个知识点都要亲自编写代码验证
    • 不要只看不练
  2. 画内存图

    • 理解对象在内存中的存储
    • 理解继承关系中对象的初始化过程
  3. 对比学习

    • 对比重写和重载
    • 对比super和this
    • 对比成员变量和成员方法的访问特点
  4. 实际应用

    • 思考继承在实际项目中的应用场景
    • 尝试设计简单的继承体系

附录:知识点速查表 ​

A. JavaBean规范 ​

组成部分要求
属性private修饰
构造方法必须有无参构造
getter方法public,返回属性值
setter方法public,设置属性值

B. 继承特点 ​

特点说明
单继承一个类只能有一个直接父类
多层继承支持多层继承体系
多子类一个父类可以有多个子类

C. 方法重写规则 ​

规则要求
权限修饰符子类 >= 父类
方法名必须相同
参数列表必须相同
返回值类型相同或是子类类型

D. super vs this ​

对比项superthis
代表父类引用当前对象
调用构造super()this()
调用变量super.变量this.变量
调用方法super.方法()this.方法()

学习格言: 继承是面向对象的核心特性之一,理解继承是掌握多态的基础。多写代码,多画图,多思考!