Java 类、对象与 this 引用入门
面向对象先看懂什么
Java 常被拿来讲面向对象。这里面最核心的不是术语,而是思路:先把现实中的事物抽象成'类',再用这个类创建具体的'对象',程序就围绕对象之间的交互去完成任务。
和面向过程相比,差别其实很直观。面向过程更关心'先做什么、后做什么',适合步骤非常固定的场景;面向对象更关心'谁来做',把属性和行为放到一起,代码会更贴近我们理解事物的方式。不是说哪一种更高级,通常只是看问题更适合哪种拆法。
类是什么,怎么写
类可以理解成对象的模板。它描述一个事物有哪些属性,也描述它能做什么。

在 Java 里,类通过 class 关键字定义:
// 创建类的基本格式
class ClassName {
// 字段(属性)或成员变量
field;
// 行为或成员方法
method;
}
类中的内容通常分成两类:成员变量,用来描述特征;成员方法,用来描述功能。
洗衣机类的例子
class WashMachine {
public String brand; // 品牌
public String type; // 型号
public double weight; // 重量
public double length; // 长
public double width; // 宽
public double height; // 高
public String color; // 颜色
public void washClothes() {
System.out.println("洗衣功能");
}
public void dryClothes() {
System.out.println("脱水功能");
}
public void setTime() {
System.out.println("定时功能");
}
}
这段代码经过 javac 编译后会生成 .class 文件,JVM 才能识别并执行。
写类的时候,有几个习惯最好先养起来:类名一般用大驼峰;成员通常先写成 public 方便理解;方法里暂时不加 static,后面再看它的区别会顺很多。
两个练习类
狗类
class PetDog {
public String name; // 狗的名字
public String color; // 狗的颜色
// 狗的属性描述
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
// 狗的行为描述
public void wag() {
System.out.println(name + ": 摇尾巴~~~");
}
}
学生类
public class Student {
public String name;
public String gender;
public short age;
public double score;
public void DoClass() {
// 上课方法
}
public void DoHomework() {
// 做作业方法
}
public void Exam() {
// 考试方法
}
}
定义类时,几个约束别混了:一般一个文件里只放一个类;带 main 方法的类通常要写成 public;public 类名要和文件名一致;类名改动时要格外小心,不然文件和类名对不上,编译器不会客气。
类是模板,对象才是实例
有了类,就可以用它创建对象。这个过程叫实例化,Java 里通常用 new 完成。
public class Student {
public String name;
public String gender;
public short age;
public double score;
public void DoClass() {}
public void DoHomework() {}
public void Exam() {}
public static void main(String[] args) {
// 通过 new 关键字实例化对象
Student s1 = new Student();
s1.name = "Li Lei";
s1.gender = "男";
s1.age = 18;
s1.score = 3.8;
Student s2 = new Student();
s2.name = "Han Meimei";
s2.gender = "女";
s2.age = 19;
s2.score = 4.0;
Student s3 = new Student();
s3.name = "Jim";
s3.gender = "男";
s3.age = 18;
s3.score = 2.6;
}
}
这里最关键的是两点:new 负责创建对象,. 用来访问对象的属性和方法。一个类可以创建很多对象,它们彼此独立,内存里各管各的。
再看一遍类和对象的关系
类本身更像设计图,不直接存放具体数据;对象才是真正占空间的实体,可以保存自己的值,也可以执行对应的方法。


下面这个例子能把'同一个类创建多个对象'这件事说得更清楚:
public class PetDog {
public String name;
public String color;
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
public void wag() {
System.out.println(name + ": 摇尾巴~~~");
}
public static void main(String[] args) {
PetDog dog1 = new PetDog();
dog1.name = "阿黄";
dog1.color = "黑黄";
dog1.barks();
dog1.wag();
PetDog dog2 = new PetDog();
dog2.name = "赛虎";
dog2.color = "棕白";
dog2.barks();
dog2.wag();
}
}
执行结果:
阿黄:旺旺旺~~~ 阿黄:摇尾巴~~~ 赛虎:旺旺旺~~~ 赛虎:摇尾巴~~~
this 引用到底在解决什么
先看一个日期类:
public class Date {
public int year;
public int month;
public int day;
public void setDay(int y, int m, int d) {
year = y;
month = m;
day = d;
}
public void printDate() {
System.out.println(year + "/" + month + "/" + day);
}
public static void main(String[] args) {
Date d1 = new Date();
Date d2 = new Date();
Date d3 = new Date();
d1.setDay(2020, 9, 15);
d2.setDay(2020, 9, 16);
d3.setDay(2020, 9, 17);
d1.printDate(); // 2020/9/15
d2.printDate(); // 2020/9/16
d3.printDate(); // 2020/9/17
}
}
这个例子能跑,但细看会冒出两个很实际的问题:如果形参名和成员变量名撞了,比如都叫 year,那 year = year; 到底是在给谁赋值?还有,d1、d2、d3 调的是同一个方法,方法体里又没写对象名,它怎么知道自己该改谁、打印谁?

答案就是 this。
this 指向当前对象,也就是调用这个成员方法的那个对象。成员方法里访问成员变量时,底层其实默认就带着这个引用,只是平时不写出来而已。
比如下面这样:
public void setDay(int year, int month, int day) {
// 此时如果写:year = year; 就会产生歧义。
// 下面使用 this 来指明是给当前对象的 year 赋值
this.year = year;
this.month = month;
this.day = day;
}
this 的几个特点
this的类型和所在类一致,谁调用方法,它就指向谁;- 它只能出现在成员方法里,静态方法里没有这个上下文;
- 它只能表示当前对象,不能在一个对象的方法里'切换'到别的对象;
- 从编译器的角度看,
this像是成员方法的第一个隐藏参数。
再看一个完整点的写法:
public class Date {
public int year;
public int month;
public int day;
public void setDay(int year, int month, int day) {
this.year = year; // this.year 表示'当前对象的 year'
this.month = month; // this.month 表示'当前对象的 month'
this.day = day; // this.day 表示'当前对象的 day'
}
public void printDate() {
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
public static void main(String[] args) {
Date d = new Date();
d.setDay(2021, 6, 9);
d.printDate(); // 2021/6/9
}
}

这一节先记住什么
类是模板,对象是实例;new 负责把类变成对象;this 用来指向当前对象,特别是在成员名和形参撞车的时候,它几乎是必需的。
后面再往下学,构造方法、封装、static、代码块这些东西,都会建立在这一层认知上。基础不复杂,但它们确实决定了你后面写 Java 时会不会越写越乱。

