【Java】2026 Java学习路线:语言根基(三)★ 核心
【Java】面向对象(OOP)★ 核心—— 语言根基(三)
Java基础必学知识点 之 语言根基(三)
一、基础概念
1. 什么是面向对象?
| 对比 | 面向过程(C语言) | 面向对象(Java) |
|---|---|---|
| 关注点 | 怎么做(步骤) | 谁来做(对象) |
| 例子 | 把大象装冰箱:1.开门 2.装进去 3.关门 | 创建三个对象:人、大象、冰箱,调用各自的方法 |
| 特点 | 数据和方法分离 | 数据和方法封装在对象中 |
- 核心: 面向对象就是把现实世界中的“东西”直接映射成程序中的“对象”,每个对象有自己的数据(属性)和操作(方法)。
2. 类与对象
- 类 (Class): 模板/蓝图,定义了一类事物共有的属性和行为。不占内存。
- 对象 (Object): 根据类创建出来的具体实例。占内存,有具体的属性值。
示例:
定义一个 Student 类,创建多个学生对象。
// 1. 定义 Student 类(模板)
public class Student {
// 成员变量(属性)
String name;
int age;
String studentId;
// 成员方法(行为)
public void study() {
System.out.println(name + " 正在学习...");
}
public void introduce() {
System.out.println("大家好,我叫 " + name + ",今年 " + age + " 岁,学号是 " + studentId);
}
}
// 2. 在另一个类(比如 Main)中创建对象
public class Main {
public static void main(String[] args) {
// 创建第一个学生对象
Student stu1 = new Student();
stu1.name = "张三";
stu1.age = 18;
stu1.studentId = "20240001";
stu1.introduce(); // 输出:大家好,我叫 张三,今年 18 岁,学号是 20240001
stu1.study(); // 输出:张三 正在学习...
// 创建第二个学生对象
Student stu2 = new Student();
stu2.name = "李四";
stu2.age = 19;
stu2.studentId = "20240002";
stu2.introduce(); // 输出:大家好,我叫 李四,今年 19 岁,学号是 20240002
}
}
Student 类定义了“所有学生都有的东西”(姓名、年龄、学习),而 stu1 和 stu2 是两个具体的、不同的学生实例。
- 成员变量(属性): 对象拥有的数据,如
name、age。 - 成员方法(行为): 对象能执行的操作,如
study()。
二、OOP 三大核心特征(重中之重)
1. 封装
-
目的: 保护数据不被外部随意修改,隐藏内部的复杂实现细节。使用时只需要通过已经提供的 方法 来操作,而不是直接碰内部零件。
-
实现:
private修饰属性 → 外部不能直接访问。public的getter/setter→ 提供受控的访问入口。
提供public的getter(获取值)和setter(设置值)方法,让外部通过方法来间接访问。在setter方法里,可以加入逻辑检查(比如余额不能为负数)。
-
示例: 一个
BankAccount类,余额不允许直接修改。
public class BankAccount {
private String owner; // 私有属性
private double balance; // 私有属性,不能直接修改
// 构造方法(稍后细讲)
public BankAccount(String owner, double initialBalance) {
this.owner = owner;
if (initialBalance > 0) {
this.balance = initialBalance;
} else {
this.balance = 0;
}
}
// Getter 方法:提供安全的读取方式
public double getBalance() {
return balance;
}
// 自定义的业务方法,而不是通用的 setter
public void deposit(double amount) { // 存款
if (amount > 0) {
balance += amount;
System.out.println("存款成功,当前余额:" + balance);
} else {
System.out.println("存款金额必须为正数");
}
}
public void withdraw(double amount) { // 取款
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("取款成功,当前余额:" + balance);
} else {
System.out.println("余额不足或金额无效");
}
}
}
// 测试
public class Main {
public static void main(String[] args) {
BankAccount myAccount = new BankAccount("张三", 1000);
// myAccount.balance = -100; // 错误!balance 是 private,无法访问
System.out.println("当前余额:" + myAccount.getBalance()); // 输出:1000.0
myAccount.deposit(500); // 输出:存款成功,当前余额:1500.0
myAccount.withdraw(2000); // 输出:余额不足或金额无效
myAccount.withdraw(200); // 输出:取款成功,当前余额:1300.0
}
}
2. 继承
-
概念: 一个类(子类)可以继承另一个类(父类)的属性和方法,实现代码复用。这是一个 “is-a” 的关系。
Dog是一个Animal。 -
关键字:
extends。 -
方法重写 (Override): 子类重新实现父类的方法。
-
super关键字:在子类中调用父类的构造方法或成员。 -
示例:
Animal→Dog/Cat
// 父类
public class Animal {
String name;
public void eat() {
System.out.println(name + " 正在吃东西");
}
}
// 子类 Dog
public class Dog extends Animal {
// 子类特有的属性
public String breed; // 品种
// 方法重写 (Override)
@Override
public void eat() {
System.out.println(name + " 正在啃骨头");
}
// 子类特有的方法
public void bark() {
System.out.println(name + " 汪汪叫");
}
}
// 子类 Cat
public class Cat extends Animal {
@Override
public void eat() {
System.out.println(name + " 正在吃鱼");
}
public void meow() {
System.out.println(name + " 喵喵叫");
}
}
// 测试
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "旺财";
dog.eat(); // 输出:旺财 正在啃骨头 (调用的是重写后的)
dog.bark(); // 输出:旺财 汪汪叫
Cat cat = new Cat();
cat.name = "咪咪";
cat.eat(); // 输出:咪咪 正在吃鱼
cat.meow(); // 输出:咪咪 喵喵叫
}
}
3. 多态
-
概念:同一个行为,作用于不同的对象,可以产生不同的结果。
-
核心语法: 通过父类引用调用子类重写的方法 。例如:
Animal myAnimal = new Dog(); -
编译时类型 vs 运行时类型:
- 编译时类型(声明类型)决定能调用哪些方法。
- 运行时类型(实际类型)决定执行哪个版本的方法。
myAnimal的编译时类型是Animal,编译器只认Animal类里的方法(比如eat())。myAnimal的运行时类型是Dog,实际执行时,会执行Dog类里重写后的方法。
- 多态的好处: 方法参数写成父类型,可以传入任意子类对象,扩展性强。
示例: 写一个 makeSound(Animal a) 方法
// 沿用上面的 Animal, Dog, Cat 类
public class Main {
// 这个方法的参数是 Animal 类型,但你可以传入任何 Animal 的子类对象
public static void makeSound(Animal a) {
// 这里展示了多态:a 可能是 Dog,也可能是 Cat
if (a instanceof Dog) {
Dog d = (Dog) a; // 向下转型
d.bark();
} else if (a instanceof Cat) {
Cat c = (Cat) a;
c.meow();
} else {
a.eat(); // 默认行为
}
}
// 更经典的多态例子
public static void letAnimalEat(Animal a) {
a.eat(); // 编译时看 Animal 有 eat(),运行时看具体子类的 eat()
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "旺财";
Cat cat = new Cat();
cat.name = "咪咪";
letAnimalEat(dog); // 输出:旺财 正在啃骨头
letAnimalEat(cat); // 输出:咪咪 正在吃鱼
makeSound(dog); // 输出:旺财 汪汪叫
makeSound(cat); // 输出:咪咪 喵喵叫
}
}
三、进阶 OOP 相关语法
1. 构造方法
-
特点: 方法名与类名相同,没有返回值。在创建对象时(
new)自动调用,用于初始化对象。 -
默认构造: 如果不写构造方法,Java 会提供默认无参构造。
-
有参构造 & 重载:你可以定义多个构造方法,参数列表不同,方便用不同方式创建对象。
public class Person {
String name;
int age;
// 无参构造
public Person() {
}
// 有参构造(重载)
public Person(String name) {
this.name = name; // 用 this 区分成员变量和参数
System.out.println("一个叫" + name + "的人被创建了");
}
// 另一个有参构造(重载)
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("姓名:" + name + ",年龄:" + age);
}
}
2. this 关键字
-
代表 当前对象 的引用。
-
用途: 区分成员变量和局部变量(如
this.name = name;)。 -
关键用法:
限制 this.属性/this.方法()只能在非静态方法/构造方法中使用 this(...)调用构造方法必须是构造方法中的第一条语句,且只能在构造方法中使用 -
示例:
public class Student {
private String name;
private int age;
// 构造方法1:两个参数
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("调用2参数构造方法");
}
// 构造方法2:只有姓名,年龄使用默认值
public Student(String name) {
this(name, 18); // 调用上面的2参数构造方法
System.out.println("调用1参数构造方法");
}
// 构造方法3:无参数,使用默认值
public Student() {
this("匿名", 18); // 调用2参数构造方法
System.out.println("调用无参数构造方法");
}
public static void main(String[] args) {
Student s1 = new Student("张三", 20);
Student s2 = new Student("李四");
Student s3 = new Student();
}
}
执行结果:
调用2参数构造方法
调用2参数构造方法
调用1参数构造方法
调用2参数构造方法
调用无参数构造方法
3. static 关键字
- 实例变量/方法 与 静态变量/方法:
| 类型 | 属于 | 访问方式 | 共享性 |
|---|---|---|---|
| 实例变量/方法 | 对象 | 对象.xxx | 每个对象独立一份 |
| 静态变量/方法 | 类 | 类名.xxx | 所有对象共享一份 |
- 静态方法中 不能直接访问 实例变量和实例方法(因为没有
this),但是可以通过对象引用来访问。
public class School {
public static String schoolName = "第一中学"; // 静态变量
public String studentName; // 实例变量
public static void printSchoolName() { // 静态方法
System.out.println("学校名称:" + schoolName);
// System.out.println(studentName); // 错误!静态方法不能访问非静态变量
}
public void printInfo() { // 实例方法
System.out.println(schoolName + " 的学生:" + studentName);
}
}
// 使用
public class Main {
public static void main(String[] args) {
System.out.println(School.schoolName); // 直接通过类名访问
School s1 = new School();
School s2 = new School();
s1.studentName = "张三";
s2.studentName = "李四";
s1.printInfo(); // 输出:第一中学 的学生:张三
s2.printInfo(); // 输出:第一中学 的学生:李四
}
}
4. 代码块
-
构造块: 写在类里,方法外的
{ }。每次创建对象时,在 构造方法之前 执行。 -
静态块:用
static { }包裹。在 类第一次加载时 执行一次,常用于初始化静态变量。
public class Demo {
static {
System.out.println("静态块:类加载时执行一次");
}
{
System.out.println("构造块:每次创建对象前执行");
}
public Demo() {
System.out.println("构造方法执行");
}
public static void main(String[] args) {
new Demo();
System.out.println("---");
new Demo();
}
}
// 输出顺序:
// 静态块:类加载时执行一次
// 构造块:每次创建对象前执行
// 构造方法执行
// ---
// 构造块:每次创建对象前执行
// 构造方法执行
四、抽象 & 接口(非常重要)
1. 抽象类
抽象类是使用 abstract 关键字修饰的类,不能被实例化,主要用于被其他类继承。
- 基本语法:
// 抽象类
public abstract class Animal {
// 普通成员变量
private String name;
// 普通方法(有实现)
public void eat() {
System.out.println("动物吃东西");
}
// 抽象方法(没有方法体)
public abstract void makeSound();
}
-
抽象方法
-
使用
abstract关键字修饰。 -
没有方法体(没有大括号和实现代码)。
-
必须以分号结尾。
// 正确:抽象方法
public abstract void doSomething();
// 错误:抽象方法不能有方法体
public abstract void doSomething() { } // 编译错误
- 抽象类特点对比总结:
| 普通类 | 抽象类 | |
|---|---|---|
| 能否实例化 | 可以 | 不可以 |
| 可以有抽象方法 | 不可以 | 可以 |
| 可以有普通方法 | 可以 | 可以 |
| 可以有构造方法 | 可以 | 可以 |
| 可以有成员变量 | 可以 | 可以 |
- 示例:
public abstract class Vehicle {
private String brand;
private int speed;
// 构造方法(子类可以调用)
public Vehicle(String brand) {
this.brand = brand;
System.out.println("Vehicle构造方法被调用");
}
// 普通方法
public void setSpeed(int speed) {
this.speed = speed;
System.out.println(brand + " 速度设置为: " + speed);
}
// 抽象方法
public abstract void start();
public abstract void stop();
}
// 子类必须实现所有抽象方法
public class Car extends Vehicle {
public Car(String brand) {
super(brand); // 调用父类构造方法
}
@Override
public void start() {
System.out.println("汽车通过点火启动");
}
@Override
public void stop() {
System.out.println("汽车踩刹车停止");
}
}
// 使用
public class Test {
public static void main(String[] args) {
// Vehicle v = new Vehicle(); // 错误:不能实例化抽象类
Car car = new Car("特斯拉");
car.start(); // 输出:汽车通过点火启动
car.setSpeed(100); // 输出:特斯拉 速度设置为: 100
car.stop(); // 输出:汽车踩刹车停止
}
}
2. 接口
- 接口定义"规则"或"标准"。
- 任何类只要遵守这些规则,就能被统一使用。
- 定义接口:
// 使用 interface 关键字,不是 class
public interface Animal {
// 接口中的方法没有方法体(没有大括号)
void eat();
void sleep();
}
- 实现接口(使用 implements 关键字):
// 类使用 implements 实现接口
public class Dog implements Animal {
// 必须实现接口中的所有方法
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗趴着睡觉");
}
}
public class Cat implements Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫蜷缩着睡觉");
}
}
- 使用接口:
public class Test {
public static void main(String[] args) {
// 接口不能直接创建对象
// Animal a = new Animal(); 错误!
// 但可以用接口引用实现类的对象(多态)
Animal dog = new Dog();
Animal cat = new Cat();
dog.eat(); // 输出:狗吃骨头
cat.eat(); // 输出:猫吃鱼
}
}
- 核心:
| 特点 | 说明 |
|---|---|
| 不能实例化 | new 接口名() 是错误的 |
| 多实现 | 一个类可以实现多个接口 |
| 多继承 | 接口可以继承多个接口 |
| 方法默认是 public abstract | 可以不写,编译器自动加上 |
接口中可以定义常量,默认是 public static final |
接口中的变量都是常量 |
- 接口的继承:
- 接口可以继承多个接口。
interface A {
void methodA();
}
interface B {
void methodB();
}
// 接口可以多继承
interface C extends A, B {
void methodC();
}
// 实现C的类必须实现所有方法(A、B、C中的)
public class MyClass implements C {
@Override
public void methodA() {
System.out.println("实现A");
}
@Override
public void methodB() {
System.out.println("实现B");
}
@Override
public void methodC() {
System.out.println("实现C");
}
}
3. 抽象类 vs 接口(初学者必知)
| 对比项 | 抽象类 | 接口 |
|---|---|---|
| 关键字 | abstract class |
interface |
| 继承/实现 | 单继承 | 多实现 |
| 构造方法 | 可以有 | 不能有 |
| 成员变量 | 可以是普通变量 | 只能是常量 |
| 普通方法 | 可以有 | 默认方法/静态方法 |
| 何时使用 | "是什么"关系 | "能做什么"关系 |
更多推荐




所有评论(0)