本节目标
- 理解面向对象思想,区分面向过程与面向对象
- 掌握类的定义、成员变量、成员方法
- 掌握类的实例化,使用
new创建对象,.访问成员 - 深度理解
this引用的作用、特性、三种用法 - 掌握对象初始化:默认初始化、就地初始化、构造方法
- 掌握构造方法重载、构造方法中
this(...)调用其他构造 - 理解直接打印对象、重写
toString()
1. 面向对象初步认知
1.1 什么是面向对象
Java 是面向对象(OOP Object‑Oriented Program) 语言,思想:一切皆对象。 面向对象是一种解决问题的思维方式,依靠对象和对象之间交互来完成业务;更加贴合人类对现实事物认知,适合大型项目开发、扩展、维护。
1.2 面向过程 vs 面向对象(洗衣服案例)

- 面向过程 :关注每一步执行的过程细节。 洗衣服:找衣服→放水→放洗衣粉→搓洗→漂洗→拧干晾晒。每一步都要自己做,流程固定。
缺点:业务改动(洗鞋子、洗被子),全部流程要重新写,维护扩展麻烦。

- 面向对象 :关注对象实体,不关心内部实现细节。 洗衣服:把衣服丢进洗衣机对象,加洗衣粉,按下启动按钮,洗衣机对象帮你完成全部工作。
用户不需要关心洗衣机内部齿轮、电机如何转动,只调用对象提供的功能即可。
注意:面向过程、面向对象不是编程语言,是两套解决问题的思想,没有绝对好坏,各有适用场景。C 语言偏向面向过程;Java 以面向对象为主。
2. 类的定义和使用
现实中有洗衣机这个实体,计算机不能直接识别。我们需要对现实事物抽象 :提取事物的属性(特征)、行为(能干什么),这个抽象产物就是类。

洗衣机实体抽象:
- 属性:品牌、型号、重量、长宽高、颜色
- 行为:洗衣服、脱水、定时
2.1 类的语法格式
java
class 类名{
// 成员变量(属性、字段 field)
// 成员方法(行为 method)
}
class:定义类的关键字- 类名:大驼峰命名法,每个单词首字母大写
- 大括号内:类的成员,包含成员变量、成员方法。
现阶段成员统一写
public修饰;本节的成员方法不带 static 关键字,是普通实例成员方法。
洗衣机类完整示例
java
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("定时功能");
}
}
2.2 课堂练习
练习 1:Dog 宠物类
属性:名字 name,颜色 color 行为:barks () 叫,wag () 摇尾巴
java
class PetDog {
//成员变量
public String name;
public String color;
//成员方法
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
public void wag() {
System.out.println(name + ": 摇尾巴~~~");
}
}
练习 2:Student 学生类
属性:姓名 name、性别 gender、年龄 age、分数 score 行为:上课 DoClass、写作业 DoHomework、考试 Exam
java
public class Student{
public String name;
public String gender;
public short age;
public double score;
public void DoClass(){}
public void DoHomework(){}
public void Exam(){}
}
⚠️类定义注意事项
- 一个
.java源文件建议只写一个类。 - 如果类被
public修饰,类名必须和文件名完全一致,大小写敏感。 - 修改 public 类名,使用 IDE 重构修改,不要手动改文件名,避免不匹配。
3. 类的实例化(创建对象)
3.1 什么是实例化
class类:相当于设计图纸 ,是自定义新的数据类型,只描述事物有什么,不占用堆内存,没有真实数据。- 实例化 :使用
new + 类名,根据图纸,在堆内存创建真实对象。一张图纸(类)可以造出很多个实物对象。
语法:
java
类名 引用变量 = new 类名();
示例,创建多个狗对象:
java
public class Main{
public static void main(String[] args) {
PetDog dogh = new PetDog(); //实例化对象1
PetDog dogs = new PetDog(); //实例化对象2
}
}
3.2 使用.访问对象成员
.点运算符:对象引用.成员变量 / 对象引用.成员方法。
java
public class Main{
public static void main(String[] args) {
PetDog dogh = new PetDog();
dogh.name = "阿黄";
dogh.color = "黑色";
dogh.barks();
dogh.wag();
PetDog dogs = new PetDog();
dogs.name = "赛虎";
dogs.color = "黄色";
dogs.barks();
dogs.wag();
}
}
输出:
java
阿黄: 旺旺旺~~~
阿黄: 摇尾巴~~~
赛虎: 旺旺旺~~~
赛虎: 摇尾巴~~~
重点理解:
- 类是图纸模型,规定有哪些成员;不占堆内存。
new出来的对象实例才占用堆物理内存,存储成员变量真实数据。- 一个类可以实例化出多个不同对象,每个对象成员变量互相独立。
- 引用变量存堆对象地址,通过
.访问对象里面的内容。

4. this 引用(核心重点)
4.1 引出 this 的两个问题
写一个 Date 日期类:
java
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();
d1.setDay(2020,9,15);
d2.setDay(2020,9,16);
d1.printDate();
d2.printDate();
}
}
两个疑问:
- 如果形参名字和成员变量名字一模一样怎么办?
java
//形参名和成员变量重名!
public void setDay(int year, int month, int day){
year = year; //局部变量year赋值给自己,成员变量完全没有修改!
month = month;
day = day;
}
就近原则:方法内部优先使用局部形参,成员变量被屏蔽,赋值无效。
d1.printDate()、d2.printDate()调用同一个方法,方法代码只有一份,方法怎么区分当前是哪个对象在调用自己?
4.2 this 引用是什么
this:成员方法当中隐藏的引用,代表当前调用这个方法的对象 。 哪个对象调用成员方法,this就指向哪一个对象。编译器自动传递,我们看不见传参过程。
修复重名问题,使用this.成员变量:
java
public void setDay(int year, int month, int day){
this.year = year; //this.year 对象的成员变量;右边year是形参
this.month = month;
this.day = day;
}
public void printDate(){
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
4.3 this 引用核心特性
- this 的类型:就是当前类的引用类型。哪个对象调用,this 就是哪个对象的引用。
- this 只能在实例成员方法、构造方法内部使用,不能在 static 静态方法中使用。
- this 代表当前对象,不能指向别的对象。
- this 是成员方法第一个隐藏参数 。调用
d1.setDay(2020,9,15),编译器底层等价setDay(d1,2020,9,15),把对象引用 d1 传给形参 this。我们代码层面看不见这个参数。

4.4 this 的三种用法
this.成员变量:访问当前对象的成员变量,解决局部变量与成员变量名字冲突(最常用)。this.成员方法():调用本类当中其他的实例成员方法。this(参数列表):只能写在构造方法第一行,调用本类其他构造方法。
注意:
this()这种调用形式只能用于构造器,普通成员方法不能写 this ()。
5. 对象的构造与初始化
5.1 局部变量 VS 对象成员变量
- 局部变量(方法里面定义) :不会自动默认初始化,使用前必须手动赋值,否则编译报错。
java
public static void main(String[] args) {
int a;
System.out.println(a); //编译报错:可能尚未初始化变量a
}
- 类的成员变量(写在类里面,方法外面) :就算不手动赋值,也会有系统默认初始值,可以直接使用。
java
Date d = new Date();
System.out.println(d.year); //输出0,有默认值
5.2 默认初始化规则
表格
| 数据类型 | 默认初始值 |
|---|---|
| byte、short、int | 0 |
| long | 0L |
| float | 0.0f |
| double | 0.0 |
| char | \u0000 |
| boolean | false |
| 所有引用类型 (String、自定义类) | null |
5.3 就地初始化
在定义成员变量的时候直接写初始值,对象 new 出来就拥有该初始值。
java
public class Date {
public int year = 1900;
public int month = 1;
public int day = 1;
}
只要 new 对象,这些成员直接被赋值。后续构造方法还可以覆盖修改这些值。
5.4 构造方法(构造器 constructor)
5.4.1 构造方法概念
构造方法是特殊的成员方法:
- 方法名字必须和类名完全一模一样,大小写一致。
- 没有返回值,连 void 都不能写!
new 对象()的时候编译器自动调用构造方法,对象生命周期中只会执行一次。- 作用:对象创建的时候,给成员变量做初始化。
示例:
java
public class Date {
public int year;
public int month;
public int day;
//构造方法
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被调用了");
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
// new的时候自动调用构造方法
Date d = new Date(1999,6,9);
d.printDate();
}
}
5.4.2 构造方法重点注意事项
- 名字必须与类名完全相同。
- 不许写返回值,写 void 也是错误,不再是构造方法,变成普通成员方法。
- new 对象时自动调用,对象一生只调用一次。
- 构造方法支持重载:方法名相同,参数列表不同,构成重载。
java
public class Date {
//无参构造
public Date(){
this.year = 1900;
this.month = 1;
this.day = 1;
}
//三参构造
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
- 编译器默认无参构造规则
如果我们一个构造方法都没有手写 ,编译器自动帮我们生成一份无参的默认构造方法 。 ⚠️一旦我们手写了任意一个构造方法(有参构造),编译器不再提供默认无参构造 !此时
new Date()直接编译报错。
错误示例:只写有参构造,再想无参实例化对象编译失败
java
public class Date {
public int year;
public int month;
public int day;
//手写有参构造,编译器不再生成无参构造!
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public static void main(String[] args) {
Date d = new Date(); //编译报错,找不到无参构造方法!
}
}
- 构造方法内部使用
this(...)调用本类其他构造方法
语法:
this(实参列表)✅强制规则:必须写在构造方法的第一行!不能放在中间或者末尾;禁止互相循环调用,会编译报错。
java
public class Date {
public int year;
public int month;
public int day;
public Date(){
this(1900,1,1); //调用三参构造,必须第一行
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
❌错误循环调用,编译报错
java
public Date(){
this(1900,1,1);
}
public Date(int year, int month, int day) {
this(); //互相调用,循环,报错
}
- 绝大多数场景构造方法使用
public;特殊场景使用private(单例模式后续讲解)。
6. 对象打印与 toString ()
直接打印对象引用变量:
java
class Person {
String name;
String gender;
int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
}
public static void main(String[] args) {
Person person = new Person("Jim","男", 18);
System.out.println(person);
}
输出类似:Person@1b6d3586
格式:
类全限定名@哈希码,不是对象里面的数据。
想要直接打印输出对象内部成员属性,重写toString()方法,把对象信息拼接成字符串返回。
java
class Person {
String name;
String gender;
int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
@Override
public String toString() {
return "[" + name + "," + gender + "," + age + "]";
}
}
public static void main(String[] args) {
Person person = new Person("Jim","男", 18);
System.out.println(person);
}
输出:[Jim,男,18]
@Override注解表示重写父类方法,继承章节详细讲解。System.out.println(对象)底层会自动调用对象的toString()得到字符串输出。
7. 课后习题
选择题:找出错误选项
A. 一个类只能实例化一个对象 B. 一个引用可以同时指向多个对象 C. Person p = null; 表示 p 这个引用指向一个空对象 D. 当一个类没有定义构造方法的时候,该类中不会默认生成构造方法
答案:A B C D 全部错误 解析:
- A 错误:一个类可以 new 出很多个实例对象。
- B 错误:一个引用同一时刻只能保存一个对象的地址,不能同时指向多个。
- C 错误:
null代表引用不指向任何对象,不存在 "空对象"。 - D 错误:没有手写任何构造,编译器自动生成默认无参构造。
代码改错题,找出所有编译错误
java
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "zhangsan";
person1.age = 10;
System.out.println(person1.name);
Person person2 = new Person("zhangfei");
person2.age = 10;
System.out.println(person2.name);
Person person3 = new Person("lisi",9);
System.out.println(person3.name);
}
}
错误分析:
- 手写了两参构造,编译器不再生成无参构造 ,
new Person()无参实例化编译报错。 new Person("zhangfei"),没有一个构造是接收单独一个字符串参数,参数列表不匹配编译报错。
修复方案:补充对应重载构造方法。
java
//补充无参构造
public Person(){}
//补充单参构造
public Person(String name){
this.name = name;
}
📔本篇核心考点总结
- 面向对象:类是图纸,对象是 new 出来的实物;类描述属性(成员变量)、行为(成员方法)。
- 实例化:
类名 引用 = new 类名();;.访问成员;一个类可以多个对象。 this:实例成员方法内代表当前调用方法的对象 ;this.成员变量解决名字冲突;this(...)调用其他构造,必须放在构造第一行。- 局部变量必须手动初始化;类的成员变量自带默认初始值。
- 构造方法:类名相同,无返回值,new 自动调用一次;支持重载;
- 不手写任何构造,编译器提供默认无参构造;
- 只要手写任意构造,编译器不再生成默认无参构造。
this(其他构造)仅在构造方法内使用,第一行,禁止循环调用。- 直接打印对象输出
类名@哈希;重写toString()可以打印对象属性信息。
面试简答 Q:构造方法能不能写 void? A:不能,写 void 之后就不再是构造方法,变成普通成员方法,new 的时候不会自动调用。 Q:
this()可以放在普通成员方法里面吗? A:不行,只能写在构造方法第一行。 Q:成员变量和局部变量区别? A:成员变量有默认初始值;局部变量没有,必须手动赋值才能使用。