1. 对象
1.1 什么是对象
在我们的日常生活中,万事万物都可以被视为对象。例如,猫咪中的"小咪"有着灰白色的毛发,而"小黑"则是黑灰色的毛发,这些都是具体的对象实例。在Java编程中,对象可以通过模板来定义:比如猫这个类别,它具有名字和毛色等属性,还能通过舔毛来清洁自己;同样地,狗这个类别也拥有名字、毛色和年龄等属性,并会通过摇尾巴来表达情绪。正是通过这些特征描述,我们才能准确地定义一个对象。
1.2 什么是面向对象
Java是一门纯面向对象的编程语言(Object Oriented Programming,简称OOP)。在面向对象的世界中,万事万物皆可视为对象。面向对象不仅是一种编程范式,更是一种解决问题的思维方式。其核心在于通过对象之间的交互来解决问题。采用面向对象的方法编写程序,能够显著提升大型项目在架构设计、功能扩展以及后期维护方面的效率与可操作性。
1.3 面向对象与面向过程
面向对象与面向过程的区别可以通过生活中的例子来理解。以洗衣场景为例:
面向对象的流程可分解为:
- 拿取衣物
- 放入洗衣机
- 加入洗衣粉
- 操作洗衣机按钮
- 等待洗衣完成
- 取出衣物
面向过程的流程则为:
- 拿取衣物
- 放入洗槽
- 加水
- 放入洗衣粉
- 手搓衣物
- 换水
- 再次手搓
- 倒水
- 拧干衣物
通过对比可以看出:
- 在面向对象的方式中,我们不需要了解洗衣机和甩干的具体实现细节,只需通过人、洗衣机、洗衣粉和衣物这四个对象的交互就能完成任务。
- 而面向过程则需要掌握衣物清洗和甩干的每个具体步骤。
这种差异在编程中同样存在。例如实现两位整数的四则运算:
- 面向对象只需调用现成的方法/函数并接收返回值
- 面向过程则需要手动编写算法实现运算功能
2. 类
2.1 什么是类
前面我们详细探讨了对象的概念,而类正是用来定义这些对象的模板
以手机为例,在Java中我们可以将其抽象为一个类:
属性包括:产品型号、品牌、重量、颜色、电池容量、处理器型号、Cmos规格等。
功能包括:拍照、社交聊天、网络浏览、音频播放、视频播放等。
那么在Java中是如何进行类的定义的呢?
2.2 类的定义
在Java中,进行类的定义需要使用到关键字class,具体语法如下:
class ClassName{ //字段(属性) 或者 成员变量 //方法 成员方法 }
其中:
- class是定义类的关键字
- ClassName是类名,需遵循大驼峰命名规范
- 大括号{}是类的主体,可以包含成员变量和成员方法
类中包含的成员分为两类:属性用于描述类的特征,称为成员属性或成员变量;方法用于定义类的功能,称为成员方法。
例如下列描述手机
class Phone{
public String brand;//品牌
public String type;//型号
public double weight;//重量
public String color;//颜色
public String cpuType;//处理器型号
public String cmosType;//相机传感器型号
public int batteryCapacity;//电池容量
//功能包括:拍照、社交聊天、网络浏览、音频播放、视频播放
public void takePhoto() {
System.out.println(brand + " " + type + " 正在拍照");
}
public void chat() {
System.out.println(brand + " " + type + " 社交聊天");
}
public void webSurfing() {
System.out.println(brand + " " + type + " 正在网络浏览");
}
public void mp3Playback() {
System.out.println(brand + " " + type + " 正在播放音频");
}
public void mp4Playback() {
System.out.println(brand + " " + type + " 正在播放视频");
}
}
3. 类的实例化
3.1 什么是实例化
当我们定义了一个类 ,就相当于在计算机中定义了一种新的类型,定义类相当于在计算机中创建了一种新类型,这与int、double、String等内置类型类似。区别在于,int、double等是语言预定义的基础类型,而类允许用户自定义新类型。例如我们之前定义的Phone类,都是这种自定义类型的体现。通过这些自定义类,我们就能创建相应的对象实例。
使用类创建对象就像根据房屋设计图建造一栋房子。图纸定义了房屋的结构,而实际建造出来的房子则是具体的实例。
而使用类 来 创建 对象 的过程就叫做 类的 实例化,在Java中采用关键字 new 来进行类的实例化 , 比如实例化上述的一个Phone 如下:
Phone phone1 = new Phone();
Phone 就像设计图纸
phone1 是为房子起的名字
new 关键字相当于施工队的开工指令
整个 new Phone() 过程就相当于完整的房屋建造流程
剖析
Phone 声明phone1变量时指定为Phone类 phone1 对象引用变量,用于指向堆中创建的对象实例 new 实例化关键字,在内存中开辟空间,调用类的构造函数并返回对象的内存地址 Phone() 执行类中定义的构造方法 Phone(){...}
,完成对象初始化:= 将创建的堆内存对象地址,存储到 phone1
引用变量中内存分配:
类可以实例化多个对象,就像可以根据同一张图纸建造多栋房子。
3.2 对象的使用
通过 引用变量名.方法名/成员变量 来使用 如下:
public static void main(String[] args) {
Phone phone1 = new Phone();
phone1.brand = "Xiaomi";
phone1.type = "14";
phone1.weight = 220;
phone1.color = "write";
phone1.cpuType = "SM8650";
phone1.cmosType = "OV50H";
phone1.batteryCapacity = 4800;
phone1.takePhoto();
phone1.chat();
phone1.webSurfing();
phone1.mp3Playback();
phone1.mp4Playback();
}
运行结果:
Xiaomi 14 正在拍照 Xiaomi 14 社交聊天 Xiaomi 14 正在网络浏览 Xiaomi 14 正在播放音频 Xiaomi 14 正在播放视频
4.this 引用
为什么要有this 引用 以及this引用能干嘛,让我们通过下面的例子来了解:
public class Date {
public int year;
public int month;
public int day;
public void setDate(int year, int month, int day) {
year = year;
month = month;
day = day;
}
public void printDate() {
System.out.println(year + "年" + month + " 月" + day + "日");
}
public static void main(String[] args) {
Date date = new Date();
date.setDate(2000,10,1);
date.printDate();
}
}
这段代码定义了一个日期类,其中包含设置日期的方法。当运行main方法时,输出结果却显示"0年0月0日"。问题出在setDate方法中:我们直接对形参进行赋值,而没有修改类的成员变量。
观察代码可以发现,setDate方法的形参与成员变量同名,导致赋值操作只修改了局部变量而非成员变量。虽然可以通过修改形参名称来解决,但更简洁的方法是使用this关键字。this引用指向当前对象实例,通过this.year可以明确指定要修改的是成员变量。
修改过后的代码如下:
public class Date {
public int year;
public int month;
public int day;
public void setDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void printDate() {
System.out.println(year + "年" + month + " 月" + day + "日");
}
public static void main(String[] args) {
Date date = new Date();
date.setDate(2000,10,1);
date.printDate();
}
}
再次运行,结果为2000年10 月1日
那么就会产生一个疑问了,为什么使用this就能使其找到成员变量了呢?
不妨将其打印出来试试,我们创建一个简单的Date类来进行验证:
public class Date {
public void print() {
System.out.println(this);
}
public static void main(String[] args) {
Date date = new Date();
date.print();
System.out.println(date);
}
}
运行过后结果如下:
Date@7ef20235
Date@7ef20235
不难发现,this传递的就是该对象的地址,那么 答案就呼之欲出了,
this和data变量指向的是同一个对象,所以在方法内部使用this时,实际上就是隐式地传递了当前对象的引用。因此,通过this访问成员变量时,JVM能够准确地找到属于该特定实例的成员变量。
5. 对象的构造以及初始化
5.1对象的初始化
对象的初始化有以下几种方式
- 就地初始化
- 通过getset等方法初始化
- 通过构造方法初始化
- 通过代码块初始化
就地初始化:
// 就地初始化示例 class Person { private String name = "无名氏"; }
通过getset等方法初始化:
public class Student { public int age; public String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void main(String[] args) { Student student1= new Student(); student1.setAge(18); student1.setName("lisi"); } }
通过构造方法初始化:
public class Student { public int age; public String name; public Student(int age, String name) { this.age = age; this.name = name; } public static void main(String[] args) { Student student1= new Student(18,"lisi"); } }
5.2 构造方法
构造方法(又称构造器)是一种特殊方法,其名称必须与所属类保持一致。当创建对象实例时,编译器会自动调用该方法,且每个对象在其生命周期内仅会被调用一次。
public class Student {
public int age;
public String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public static void main(String[] args) {
Student student1= new Student(18,"lisi");
}
}
需要注意的是,如果当我们没有写构造方法,那么编译器便会生成一个默认的构造方法用于调用,不过该构造方法参数为空,代码块为空,其结构如下:
public 类名() { //为空 }
如果当我们写了构造方法,那么系统就不会生成该构造方法
*构造方法一般用于对对象中的成员进行初始化
值得一提的是,构造方法可以重载,如下:
public class Student { public int age; public String name; public Student(int age, String name) { this.age = age; this.name = name; System.out.println("这是一个带有3个参数的构造方法"); } public Student() { System.out.println("这是一个不带参数的构造方法"); } public static void main(String[] args) { Student student1= new Student(18,"lisi"); } }
在构造方法中,可以通过this来调用其他构造方法,如下:
public class Student { public int age; public String name; public Student(int age, String name) { this(); this.age = age; this.name = name; System.out.println("这是一个带有3个参数的构造方法"); } public Student() { System.out.println("这是一个不带参数的构造方法"); } public static void main(String[] args) { Student student1= new Student(18,"lisi"); } }
运行结果:
这是一个不带参数的构造方法 这是一个带有3个参数的构造方法
注意:this(...)必须是构造方法中的第一条语句,且不能与其他构造方法形成闭环
public Student(int age, String name) { this(); this.age = age; this.name = name; System.out.println("这是一个带有3个参数的构造方法"); } public Student() { this(19,"lisi") System.out.println("这是一个不带参数的构造方法"); } //error 形成环了