Java中一切皆对象!
Java是一门纯面向对象的语言(Object Oriented Program,简称OOP)。一切皆对象,面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事。
– 面试官问你OOP是啥,要知道是面向对象。
比如:买手机
面向过程:关注买手机的过程
上网查配置 ——> 打开购物平台 ——> 选参数 ——> 选手机 ——> 下单 ——> 填地址 ——> 付款 ——> 取快递 ——> 使用
面向对象:不关注买手机的过程,只关注对象,通过对象之间的交互来完成。
①给秘书说要买手机
②秘书帮我买手机:查参数……
③我使用
在 我、秘书、手机 三个实体对象之间相互协作完成。
要是拿到一个对象,必须先类!
类返回对象的过程——实例化
类: Java中通过 “类” 来描述事物,类主要是由 “属性” 和 “行为” 构成。
如:洗衣机
类:洗衣机
属性:品牌、型号、产品重量、外观尺寸、颜色……
行为:洗衣、烘干、定时……
对象: 某个事物的具体存在
【类和对象的关系】
类:属性和行为的集合,是一个抽象的概念
对象:是该类事物的具体体现,是一种具体存在
举例:
【如何定义一个类】
就是把一系列相关事物共同属性和行为抽取出来的过程(抽象)
// 创建洗衣机类
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 class Test {
public static void main(String[] args) {
WashMachine w1 = new WashMachine(); //类的实例化
w1.brand = "美的"; //访问属性
System.out.println(w1.brand);
w1.washClothes(); //访问方法
}
}
【注意】
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只是指向了一个对象,就是最后一个
1. 概述
这个.
表示本类对象的引用,本质是一个对象。
2. 特性
每一个普通方法都有一个this,谁调用该方法,this就指向谁。
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。
我们知道,在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方法设置具体的日期,比较麻烦,那对象该如何初始化?
②局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?
【概述】
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
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修饰(后续将单例模式时会遇到)。
在上文提出的第二个问题:为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?
在调用构造方法给对象赋值之前,系统内部会自动默认初始化。
要搞清楚这个过程,就需要知道 new 关键字背后所发生的一些事情:
Date d = new Date(2021,6,9);
在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍下:
检测对象对应的类是否加载了,如果没有加载则加载;
为对象分配内存空间;
处理并发安全问题;
比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突;
设置对象头信息(关于对象内存模型后面会介绍);
调用构造方法,给对象中各个成员赋值。
在声明成员变量时,就直接给出了初始值。
public class Date {
//定义初始值
public int year = 1900;
public int month = 1;
public int day = 1;
public Date(){
}
注意:代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中