前言
作为新手小白,刚接触Java时,“面向对象”可能是第一个让你感到抽象的概念。别怕,这篇文章会从最基础的思想讲起,一步步带你理解什么是对象、类,以及面向对象的三大特性:封装、继承、多态。
第一部分:面向对象基础
1. 面向过程 vs 面向对象
· 面向过程:把问题拆解成一步步的步骤,按顺序执行(像做菜教程)。
· 面向对象:先找出程序里有哪些“对象”,然后让这些对象互相配合来解决问题(像导演安排演员)。
Java是面向对象的语言,所以我们要用“对象”的思维来写程序。
2. 对象是什么?
· 对象 = 客观世界里的任何事物,在Java中的表现。
· 对象由两部分组成:
· 属性(静态特征):比如人的姓名、年龄。
· 方法(动态行为):比如人吃饭、走路。
3. 类和对象的关系
· 类 = 对象的模板(蓝图)。
· 对象 = 根据类创建出来的具体实例。
比如:Student 是一个类,而 new Student() 创建的就是一个具体的学生对象。
4. 类的组成(重点)
一个标准的类包含三样东西:属性、方法、构造方法。
① 属性(成员变量)
· 定义在类里面、方法外面。
· 有默认值(int→0,double→0.0,boolean→false,引用→null)。
· 可以和局部变量重名,重名时在方法内优先使用局部变量(如果想用成员变量,用 this 区分)。
```java
public class Student {
String name; // 成员变量
int age;
}
```
② 方法(成员方法)
· 描述对象能做什么。
· 定义格式:public 返回值类型 方法名(参数列表) { 方法体 }
· 方法重载(Overload):同一个类中,方法名相同,但参数列表不同(个数、类型、顺序)。
好处:让方法更灵活,比如 System.out.println() 可以打印各种类型。
```java
public class Calculator {
public int add(int a, int b) { return a + b; }
public double add(double a, double b) { return a + b; } // 重载
}
```
③ 构造方法(构造器)
· 方法名和类名完全相同,没有返回值(连void都不写)。
· 作用:给属性赋初始值(对象创建时自动调用)。
· 如果没写任何构造方法,系统会默认给一个无参构造。但如果写了有参构造,系统就不再提供默认无参构造(建议手动写上无参构造)。
```java
public class Student {
String name;
int age;
// 无参构造
public Student() {}
// 有参构造
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
```
5. 对象的创建和使用
```java
Student s = new Student("小明", 18);
System.out.println(s.name); // 访问属性
s.age = 19; // 修改属性
s.study(); // 调用方法
```
6. this 关键字(重要)
· this. 代表当前对象,用来区分成员变量和局部变量。
· this() 调用本类的其他构造方法,必须写在构造方法的第一行。
```java
public Student() {
this("默认名字", 0); // 调用有参构造
}
```
7. 引用与内存(理解)
· 引用 = 对象类型的变量,存储的是对象在堆内存中的地址。
· 引用赋值为 null 时,调用方法会报 NullPointerException(空指针异常)。
· 引用之间赋值传递的是地址,基本类型赋值传递的是数值。
第二部分:面向对象的三大特性
一、封装(Encapsulation)
封装就是把对象的属性和实现细节隐藏起来,只对外暴露必要的接口(方法)。
1. 访问修饰符
Java有四种访问修饰符,它们的可见范围从小到大依次是:
· private:仅在本类内部可见,对外完全隐藏。
· default(不写):在本类和同一个包内的其他类可见(包括同包子类)。
· protected:在本类、同包类以及不同包的子类中可见。
· public:在任何位置都可见,完全没有限制。
理解这个顺序后,我们就能根据需求控制属性和方法的暴露程度。
2. 封装的具体做法
· 属性私有化:用 private 修饰属性。
· 提供公开的 get/set 方法:让外界通过方法来访问和修改属性。
```java
public class Person {
private String name;
private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) {
if (age >= 0) { // 可以在set里加逻辑控制
this.age = age;
}
}
}
```
封装的好处:保护数据安全,提高代码的可维护性。
二、继承(Inheritance)
继承表示类与类之间的 is-a 关系(子类是一种父类)。
例如:Dog 是一种 Animal,所以 Dog extends Animal。
1. 语法
```java
class 子类 extends 父类 {
// 子类特有内容
}
```
2. 继承的好处
· 提高代码复用性(子类可以直接使用父类的属性和方法)。
· 提高代码可扩展性。
3. 方法重写(Override)【重点】
子类可以重新定义父类中已有的方法(方法名、参数列表、返回值类型完全相同)。
· 访问修饰符不能比父类更严格(比如父类是 public,子类不能是 protected)。
· 重写后,子类对象调用该方法会优先使用子类的版本。
```java
class Animal {
public void shout() {
System.out.println("动物叫");
}
}
class Dog extends Animal {
@Override
public void shout() {
System.out.println("汪汪汪");
}
}
```
重载 vs 重写:
· 重载(Overload):同一个类,方法名相同,参数不同。
· 重写(Override):子父类之间,方法签名完全一样。
4. 子类能继承父类的哪些内容?
· 构造方法不能继承(因为构造方法名必须和类名一致)。
· 属性和方法能否继承取决于访问修饰符:
· private 修饰的完全不能继承。
· default 修饰的只有同包子类可以继承。
· protected 和 public 修饰的都可以被子类继承(protected 允许不同包的子类继承)。
5. super 关键字
· super() 或 super(参数):在子类构造方法中调用父类的构造方法,必须写在第一行。
· super.属性 / super.方法():在子类中调用父类的属性或方法(当子类覆盖了父类方法时,可以用 super 调用父类版本)。
```java
class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类有参构造
}
public void printShout() {
super.shout(); // 调用父类的shout方法
}
}
```
6. Java继承特点
· 单继承:一个类只能有一个直接父类(但可以多级继承:A→B→C)。
· 创建子类对象时,会先创建父类对象(递归),所以构造方法调用顺序是:父类构造 → 子类构造。
三、多态(Polymorphism)
多态 = 同一个行为,不同对象表现出不同的形态。
比如:Animal 类型的引用指向 Dog 对象,调用 shout() 时实际执行的是 Dog 的 shout()。
1. 多态的前提
· 有继承关系。
· 有方法重写。
· 父类引用指向子类对象(向上转型)。
```java
Animal a = new Dog(); // 父类引用指向子类对象
a.shout(); // 输出 "汪汪汪"(多态)
```
2. 类型转换
· 向上转型(自动):Animal a = new Dog();
· 向下转型(强制):Dog d = (Dog) a;(需要先用 instanceof 检查,避免 ClassCastException)
```java
if (a instanceof Dog) {
Dog d = (Dog) a;
d.eat(); // 调用Dog特有的方法
}
```
3. 多态的实际应用(开发中很常用)
· 多态数组:数组类型是父类,可以存储任何子类对象。
· 多态参数:方法参数写成父类,可以传入任意子类对象。
· 多态返回值:方法返回父类类型,可以返回任意子类对象。
```java
// 多态参数示例
public void feed(Animal a) {
a.shout();
}
// 调用时可以传 Dog、Cat 等
feed(new Dog());
feed(new Cat());
```
4. 多态的好处
· 屏蔽不同子类的差异,统一处理。
· 让程序更加灵活、可扩展(新增子类不影响已有代码)。
总结:
现在我们把三大特性串起来回顾一下:
· 封装:用 private 隐藏属性,通过 get/set 控制访问,保护数据安全,降低耦合。
· 继承:用 extends 建立父子关系,子类复用父类代码,通过方法重写实现个性,记得构造方法和 super 的规则。
· 多态:用父类引用指向子类对象,配合重写,让同一个方法调用表现出不同行为,同时利用 instanceof 安全转型,让程序更灵活通用。
学习面向对象,最重要的是理解概念,然后动手敲代码。建议自己写几个小类(比如 Person、Student、Teacher),把封装、继承、多态都用上,感受它们是如何协作的。
如果这篇文章对你有帮助,欢迎点赞收藏~ 有问题也可以在评论区交流😃