封装、继承、多态——这三个词背了无数遍,但说实话,真正理解面向对象是在写了上万行代码之后。刚学的时候觉得这些概念很抽象,后来在工作中慢慢体会到OOP的好处。这篇文章用代码实例讲清楚OOP的核心概念,希望能帮你少走弯路。
Java面向对象编程基础详解
什么是面向对象编程?
简单说,OOP就是把现实世界的东西映射成代码里的”对象”。比如写个电商系统,可以把”用户”、“商品”、“订单”分别抽象成类。Java从一开始就是为OOP设计的,虽然严格来说基本类型不算对象。
刚开始学的时候我觉得OOP很绕,明明用函数就能搞定的事为什么要搞这么复杂。后来写了一个上千行的项目,没有OOP的话代码根本没法维护,那时候才体会到封装和继承的好处。
三个核心概念
1. 类(Class)—— 对象的图纸
类就是对象的模板。就像盖房子需要设计图一样,创建对象需要先定义类。
public class Person { private String name; private int age;
public Person(String name, int age) { this.name = name; this.age = age; }
public void sayHello() { System.out.println("Hello, my name is " + name); }}2. 对象(Object)—— 类的实例
Person person = new Person("张三", 25);person.sayHello();3. 封装(Encapsulation)
把属性和行为打包在一起,对外隐藏实现细节。关键是:
private修饰成员变量- 提供
public的getter/setter
这么搞的好处是,以后想改内部实现(比如把name拆成firstName+lastName),外面调用方不用改任何代码。
4. 继承(Inheritance)
子类继承父类的属性和方法,实现代码复用。
public class Animal { protected String name;
public Animal(String name) { this.name = name; }
public void eat() { System.out.println(name + " is eating"); }}
public class Dog extends Animal { public Dog(String name) { super(name); }
@Override public void eat() { System.out.println(name + " is eating bones"); }
public void bark() { System.out.println(name + " is barking"); }}Java只支持单继承,一个子类只能有一个直接父类。这是为了避免C++里多继承的菱形问题。
5. 多态(Polymorphism)
同一个方法调用,根据对象不同表现出不同行为。
Animal animal = new Dog("旺财");animal.eat(); // 输出:旺财 is eating bones
// 向下转型if (animal instanceof Dog) { Dog dog = (Dog) animal; dog.bark();}多态的关键三要素:继承、方法重写、父类引用指向子类对象。
构造方法
构造方法名和类名相同,没有返回值,创建对象时自动调用。如果没写,编译器会生成一个默认无参构造。但如果写了有参构造,默认无参构造就没了——这个坑我踩过。
public class Person { private String name; private int age;
public Person() {} public Person(String name) { this.name = name; } public Person(String name, int age) { this.name = name; this.age = age; }}this 和 super
this:当前对象的引用,用来区分成员变量和局部变量super:父类的引用,调用父类构造方法或方法
public Dog(String name) { super(name); // 调用父类构造,必须放在第一行}重写 vs 重载
重写(Override):子类重新实现父类的方法,方法签名必须相同。
重载(Overload):同一个类里方法名相同,参数列表不同。返回值可以不同,但光返回值不同不算重载。
public class Calculator { public int add(int a, int b) { return a + b; } public double add(double a, double b) { return a + b; } public int add(int a, int b, int c) { return a + b + c; }}抽象类和接口
抽象类:不能被实例化,用来定义子类的共同行为。可以有抽象方法(子类必须实现)和普通方法。
接口:更纯粹的抽象,只定义契约(Java 8+可以有默认方法和静态方法)。一个类可以实现多个接口。
什么时候用抽象类,什么时候用接口?有个简单的判断标准:关系是”is-a”(是什么)用抽象类,关系是”can-do”(能做什么)用接口。比如Dog extends Animal,但Dog implements Swimmable。
SOLID原则
- 单一职责:一个类只干一件事
- 开闭原则:对扩展开放,对修改关闭
- 里氏替换:子类应该能替换父类
- 接口隔离:接口要小而专
- 依赖倒置:面向抽象编程,不面向具体编程
以前见过一个项目,继承层级有七八层,改一个底层类上面全受影响,后来全部重构成了组合模式。所以记住:优先使用组合而非继承。
💡 实战贴士: 写代码的时候多想想”如果需求变了,我的代码改动量有多大”。好的OOP设计,改一个需求只需要改一个地方,而不是满世界找代码改。尤其是接口和抽象类的设计,前期多花点时间想清楚,后期能省很多事。
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时






