文章目录
- 一、面向对象的初步认识
- 1. 什么是面向对象
- 2. 面向对象与面向过程
- 二、类和对象
- 三、类的定义和使用
- 四、类的实例化
- 五、this引用
- 六、对象的构成及初始化
- 1. 如何初始化对象
- 2. 构造方法
- 3. 默认初始化
- 4. 就地初始化
一、面向对象的初步认识
1. 什么是面向对象
Java中一切皆对象!
Java是一门纯面向对象的语言(Object Oriented Program,简称OOP)。一切皆对象,面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事。
– 面试官问你OOP是啥,要知道是面向对象。
2. 面向对象与面向过程
比如:买手机
面向过程:关注买手机的过程
上网查配置 ——> 打开购物平台 ——> 选参数 ——> 选手机 ——> 下单 ——> 填地址 ——> 付款 ——> 取快递 ——> 使用
面向对象:不关注买手机的过程,只关注对象,通过对象之间的交互来完成。
①给秘书说要买手机
②秘书帮我买手机:查参数……
③我使用
在 我、秘书、手机 三个实体对象之间相互协作完成。
要是拿到一个对象,必须先类!
类返回对象的过程——实例化
二、类和对象
类: Java中通过 “类” 来描述事物,类主要是由 “属性” 和 “行为” 构成。
如:洗衣机
类:洗衣机
属性:品牌、型号、产品重量、外观尺寸、颜色……
行为:洗衣、烘干、定时……
对象: 某个事物的具体存在
【类和对象的关系】
-
类:属性和行为的集合,是一个抽象的概念
-
对象:是该类事物的具体体现,是一种具体存在
-
举例:
- 手机(类)
- 张三的手机(对象)
三、类的定义和使用
【如何定义一个类】
就是把一系列相关事物共同属性和行为抽取出来的过程(抽象)
- 类: class为定义类的关键字;
- 成员变量: 事物的属性,写在类中,方法外;
- 成员方法: 事物的行为,写在类中。
// 创建洗衣机类
class WashMachine{
//定义成员变量
public String brand; //品牌
public String type; // 型号
public String color; // 颜色
//定义成员方法
public void washClothes(){ // 洗衣服
System.out.println("洗衣功能");
}
public void dryClothes(){ // 脱水
System.out.println("脱水功能");
}
public void setTime(){ // 定时
System.out.println("定时功能");
}
}
【注意】
- 类名注意采用大驼峰定义;
- 成员变量前写法统一为 public;
- 成员方法不带static。
四、类的实例化
定义了一个类,就相当于在计算机中定义了一种新的类型。用 “类” 类型创建对象的过程,成为类的实例化。
- 用new关键字创建一个对象的实例;
- 用
.
来访问对象中的属性和方法; - 一个类可以创建多个对象。
如:接上述洗衣机代码
public class Test {
public static void main(String[] args) {
WashMachine w1 = new WashMachine(); //类的实例化
w1.brand = "美的"; //访问属性
System.out.println(w1.brand);
w1.washClothes(); //访问方法
}
}
【输出结果】
【注意】
- 当一个引用,赋值为 null 的时候,代表这个引用不指向任何对象 ,报空指针异常!
WashMachine w = null;
w.brand = "haha";
System.out.println(w.brand); //不指向任何对象,此时会报空指针异常
- 引用也不能指向引用,引用要指向对象。
WashMachine w1 = new WashMachine();
WashMachine w2 = new WashMachine();
w1 = w2; //错误,这个代表w1这个引用 指向了 w2这个引用指向的对象,此时,w1和w2所指向一个地址。
- 一个引用也不能指向多个对象
WashMachine wm1 = new WashMachine();
wm1 = new WashMachine();
wm1 = new WashMachine();
wm1 = new WashMachine(); //最后wm1只是指向了一个对象,就是最后一个
五、this引用
1. 概述
这个.
表示本类对象的引用,本质是一个对象。
2. 特性
每一个普通方法都有一个this,谁调用该方法,this就指向谁。
- this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型;
- this只能在“成员方法”中使用;
- 在“成员方法”中,this只能引用当前对象,不能再引用其他对象;
- this是“成员方法”第一个隐藏的参数,编译器会自动传递,再成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this来接收u。
3. 用法
①this访问成员变量(this.data;);
public void srtDate(int year,int month,int day) {
//加上this 来表示给当前的对象的属性赋值。
this.year = year;
this.month = month;
this.day = day;
}
②this访问成员方法(this.func());
public int year;
public int month;
public int day;
this.show(); //访问成员方法
public void setDate(int year, int month, int day) {
this.show(); //访问成员方法
this.year = year; //为当前对象的year赋值,前面的是当前对象,后面的是局部变量。
this.month = month;
this.day = day;
}
③this访问构造方法(this(…))。
public int year;
public int month;
public int day;
//构造方法
public DateUtil() {
//this访问构造方法
this(1999,9,9);
System.out.println("不带参数的构造方法!");
}
public DateUtil(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
this不能调用静态的 成员方法 和 属性。
4. 总结
局部变量和成员变量重名(如:age),则 this.age为局部变量。
以后要习惯使用this。
六、对象的构成及初始化
1. 如何初始化对象
我们知道,在Java方法内部定义一个局部变量时,必须要初始化,否则编译失败。
public static void main(String[] args) {
int a;
System.out.println(a);
}
// Error:(26, 28) java: 可能尚未初始化变量a
如果要让上述代码通过编译,只需给定a一个初始值即可。但如果是对象,
public static void main(String[] args) {
Date d = new Date();
d.printDate();
d.setDate(2021,6,9);
d.printDate();
}
// 代码可以正常通过编译
需要调用之前写的setDate方法才能将具体的日期设置到对象中,通过上述例子,我们发现两个问题:
①每次对象创建好后调用setDaye方法设置具体的日期,比较麻烦,那对象该如何初始化?
②局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?
2. 构造方法
【概述】
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
Dog d = new Dog();
这里是实例化对象,此时会调用对象的构造方法。
当我们调用完构造方法,对象就生成了!! 生成对象分两步:
①为对象分配内存;
②调用合适的构造方法。
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.month = month;
this.day = day;
}
//成员方法
public void printDate(){
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
//构造方法
public Date() {
System.out.println("不带参数的构造方法")
}
public static void main(String[] args) {
// 构造三个日期类型的对象 d1 d2 d3
Date d1 = new Date();
Date d2 = new Date();
Date d3 = new Date();
// 对d1,d2,d3的日期设置
d1.setDay(2020,9,15);
d2.setDay(2020,9,16);
d3.setDay(2020,9,17);
// 打印日期中的内容
d1.printDate();
d2.printDate();
d3.printDate();
}
}
//此时输出
不带参数的构造方法
2020/9/15
不带参数的构造方法
2020/9/16
不带参数的构造方法
2020/9/17
可以实例化对象给构造方法传参,此时不用调用上述的setDate方法:
//要手动加入不带参数的构造方法,不管写了啥构造方法,此时Java都不会提供不带参数的构造方法了
public Date() {}
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("带有3个参数的构造方法");
}
public static void main(String[] args) {
Date d = new Date(2021,6,9);
d.printDate();
}
//输出
带有3个参数的构造方法
2021-6-9
【特性】
①名字必须与类名相同;
②没有返回值类型,设置void也不行;
③创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次);
④构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)。
⑤如果用户没有显示定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的;其中注意,一旦用户定义,编译器则不再自动生成默认的构造方法。
⑥构造方法中,可以通过this调用其他构造方法来简化代码。
public int year;
public int month;
public int day;
//构造方法
public DateUtil() {
this(1999,9,9);
System.out.println("不带参数的构造方法!");
}
public DateUtil(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
注意:
上述无参方法中的this(1999,9,9);
就是调用当前对象的其他构造方法。此语句 ① 必须放在第一行;② 只能在构造方法内部才能使用。③ 不能成环。(就是不能两个及以上的构造方法使用this(…),这样会在其内部踢皮球了。)
⑦绝大多数情况下使用 public 来修饰,特殊场景下会被private修饰(后续将单例模式时会遇到)。
3. 默认初始化
在上文提出的第二个问题:为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?
在调用构造方法给对象赋值之前,系统内部会自动默认初始化。
要搞清楚这个过程,就需要知道 new 关键字背后所发生的一些事情:
Date d = new Date(2021,6,9);
在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍下:
-
检测对象对应的类是否加载了,如果没有加载则加载;
-
为对象分配内存空间;
-
处理并发安全问题;
比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突; -
初始化所分配的空间
即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:
-
设置对象头信息(关于对象内存模型后面会介绍);
-
调用构造方法,给对象中各个成员赋值。
4. 就地初始化
在声明成员变量时,就直接给出了初始值。
public class Date {
//定义初始值
public int year = 1900;
public int month = 1;
public int day = 1;
public Date(){
}
注意:代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中