大家好,我是夏幻灵,今天带大家跨入Java编程的核心领域------面向对象编程。这是Java语言的灵魂所在。本篇我们将攻克最基础也是最重要的两个概念:"类"与"对象",并深入探讨面向对象三大特征之一的"封装"。
一、 类与对象的本质
在面向对象的世界里,我们通常这样定义二者的关系:
-
类:是对一类事物的抽象描述,是共同特征的集合。它是一种自定义的数据类型。
-
对象是类的一个具体实例,是真实存在的实体。
1.1 形象化理解:模具与饼干
如果把"类"比作一个饼干模具 ,那么"对象"就是用这个模具压出来的一块块饼干。
-
模具(类)决定了饼干的形状和大小,但模具本身不能吃。
-
饼干(对象)才是我们可以实际操作、享用的实体。
-
一个模具可以制造出无数个饼干,每个饼干的状态(比如有没有烤焦)可能不同,但结构是一致的。
1.2 现实生活的映射
先有类,后有对象。 这是Java设计的核心逻辑。 举个例子:
-
需求:你想打扫家里的地板。
-
寻找方案(找类):你需要一种能自动扫地的机器,我们称之为"扫地机器人"。
-
实例化(建对象):光有"扫地机器人"这个概念是扫不了地的,你必须去商店买一台真实的、具体的机器人回家,这台机器才是能工作的"对象"。
二、 类的定义与规范
在Java中,类通过属性(数据)和方法(行为)来描述事物。我们将数据和行为封装在一起,对外隐藏复杂的实现细节。
2.1 基本语法结构
Java
public class 类名 {
// 1. 成员变量(属性):描述对象"有什么",通常是名词
// 2. 成员方法(行为):描述对象"能做什么",通常是动词
// 3. 构造器:用于初始化对象
// 4. 代码块
// 5. 内部类
}
2.2 编写规范
-
命名规范:类名首字母建议大写(大驼峰命名法),且要见名知意。
-
文件规范 :虽然一个
.java源文件中可以定义多个class,但只能有一个被public修饰,且该类名必须与文件名一致。为了代码清晰,强烈建议一个文件中只写一个类。
三、 类与类之间的关系图谱
在复杂的系统中,类不是孤立存在的,它们之间存在多种关系:
-
继承关系 (Is-a):
-
描述:子类继承父类的属性和方法,可以重写或扩展。
-
关键字:
extends。
-
-
实现关系 (Can-do):
-
描述:类实现接口中定义的规范(方法)。
-
关键字:
implements。
-
-
关联关系 (Has-a):
-
描述:类与类之间长期的引用关系。
-
细分:
-
聚合:整体与部分可以分离(如:班级和学生)。
-
组合:整体与部分同生共死(如:人和心脏)。
-
-
-
依赖关系 (Uses-a):
- 描述:一种临时性的使用关系。例如在方法参数中用到了另一个类的对象。
四、 面向对象核心特征:封装 (Encapsulation)
封装,通俗来说就是"把该藏的藏起来,该露的露出来"。它是面向对象三大特征(封装、继承、多态)的基石。
4.1 封装的基本原则
对象代表什么,就得封装对应的数据,并提供数据对应的行为。 通过访问修饰符来控制可见性:
-
public:对外完全公开。 -
protected:对子类和同包公开。 -
default(不写):仅对同包公开。 -
private:仅对自己公开(私有)。
4.2 为什么需要封装?(四大优势)
-
安全性:隐藏内部实现细节,防止外部随意篡改核心数据。
-
解耦合:内部逻辑的改变不会影响外部调用者,也就是"高内聚,低耦合"。
-
复用性:将通用的逻辑封装成单元,可以在不同场景下重复使用。
-
易用性:调用者不需要知道复杂的底层逻辑,只需要调用公开的接口(方法)即可。
4.3 实战代码演示:标准的JavaBean
下面是一个标准的Person类封装示例。我们通过private隐藏属性,通过public的Getter/Setter方法暴露访问接口。
Java
public class Person {
// 1. 私有化成员变量(隐藏数据)
private int age;
private String name;
// 2. 提供构造方法(初始化数据)
public Person(int age, String name) {
this.age = age;
this.name = name;
}
// 无参构造器(建议习惯性加上)
public Person() {}
// 3. 公开的成员方法(暴露行为)
public void sayHello() {
System.out.println("Hello, my name is " + name + ". I'm " + age +" years old.");
}
// 4. 提供Getter/Setter方法(控制数据的读写)
// 外界通过此方法修改name
public void setName(String name) {
this.name = name;
}
// 外界通过此方法获取name
public String getName() {
return name;
}
// 可以在Setter中增加逻辑判断,例如防止年龄为负数
public void setAge(int age) {
if(age >= 0 && age <= 150) {
this.age = age;
} else {
System.out.println("年龄输入不合法");
}
}
public int getAge() {
return age;
}
}
4.4 封装的进阶思考
封装不仅仅是把变量变成private这么简单。它赋予了我们控制数据的能力:
-
只读属性 :只提供
get方法,不提供set方法。 -
只写属性 :只提供
set方法,不提供get方法。 -
逻辑校验 :在
set方法中加入if判断,确保存入的数据是合法的(如上面的年龄判断)。
Java官方库中封装了海量的类供我们直接调用,理解了封装的思想,我们才能更好地站在巨人的肩膀上进行开发。