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.方法()

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