目录
1.面向对象
1.1什么是面向对象
1.2与面向过程的比较
2类的定义和使用
2.1简单认识类
2.2类的定义格式
2.3类的实例化
2.3.1什么是实例化
2.3.2类和对象的说明
2.3.3this关键字
2.3.4什么是this引用
2.3.5this引用的特性
3.对象的构造和实例化
3.1对象的初始化
4.构造方法
4.1概念
4.2特性
5.默认初始化
6.就地初始化
1.面向对象
1.1什么是面向对象
Java是一门纯面向对象的语言(Object Oriented Program简称OOP,故面向对象语言也叫做OOP语言),在面向对象的世界里一切皆对象。面向对象是一种解决问题的思想,主要依赖于对象之间的交互完成一件事情。用面向对象的思想来涉及程序更符合人们对事务的认知,对于大型型程序的设计,扩展以及维护都非常友好。
1.2与面向过程的比较
假如我们需要去洗衣服,一般来说有两种方式,即手洗和机洗。手洗的话我们需要放水,添加洗涤剂,然后手搓,发现哪里有污渍,要用更大的力气去搓,以及洗完后用清水漂洗等等过程,而机洗呢,我们只需要把衣服放进去,加入洗涤剂,启动洗衣机即可。两种方式都可以达到衣物清洗干净的目的。手洗我们通常会关心怎么洗,而机洗却不用关心这个问题。虽然说两种方式都可以清洗衣物,手洗虽然费力但是省电省水,机洗虽然轻松,但是会费水费电。不能说哪种方式就一定更好。就像面向过程的语言执行起来效率更高,但是开发难度高,开发时间长,面向对象的语言开发效率高,难度低,但是执行起来很多时候并没有面向过程的语言那么地高效。孰优孰劣,两者并不能一概而论。
2类的定义和使用
2.1简单认识类
类是用来对一个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性,哪些功能。
2.2类的定义格式
在Java中定义类时需要用到class关键字,具体语法如下:
//创建类
class ClassName {
field; //字段(属性)或者成员变量
method; //行为或者成员方法
}
class为定义类的关键字,ClassName为类的名字,{}中为类的主体。
类中包含的类容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者成员变量。
方法主要说明类具体有哪些功能,称为成员方法。
class WashMachine {
public String brand;
public double weight;
public double height;
}
public void washClothes() {
System.out.println("洗衣服的功能");
}
public void dryClothes() {
System.out.println("脱水的功能");
}
采用Java语言将洗衣机类在计算机中定义完成,经过javac编译后形成class文件,在JVM的基础上计算机就可以识别了。
注意事项
- 类名注意采用大驼峰定义
- 成员前写法统一为public
- 此处方法不带static关键字
2.3类的实例化
2.3.1什么是实例化
定义了一个类,就相当于在计算机中定义了一种新的类型,与int,double类似,只不过int和double是Java语言自带的内置类型,而类是用户定义了一种新的类型。有了自定义的类型后,就可以使用这些类来定义实例(对象)。
用类类型创建对象的过程,称为类的实例化,在Java中采用new关键字,配合类名实例化对象。
public class void mian(String[] args) {
WashMachine n=new WashMachine();
n.brand1="格力";
n.wieght=195.3;
n.height=1.4;
}
class WashMachine {
String brand;
double weight;
double hieght;
}
注意事项
- new关键字用于创建一个对象的实例
- 使用.来访问对象中的属性和方法
- 同一个类可以创建多个实例
2.3.2类和对象的说明
- 类只是一个模型一样的东西,用来对一个实体描述,限定了类有哪些成员。
- 类是一种自定义类型,可以用来定义变量。
- 一个类可以实例化出多个对象,实例化出的对象占用实际物理空间,存储类成员变量
- 类实例化就像现实中使用图纸造房子,类就是设计图,只设计出需要什么东西,并没有实体的建筑存在,同样地类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间。
2.3.3this关键字
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) {
// 构造三个日期类型的对象 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();
}
}
以上代码定义了一个日期类,然后main方法中创建了三个对象,并通过Date类中的成员方法对对象进行设置和打印。
但是细想一下会发现两个问题
1.形参不小与成员变量名相同
public void setDay(int year,int month,int day) {
year=year;
month=month;
day=day;
}
那函数到底是在给谁赋值?这是一个说不清的问题了。
2.三个对象都在调用setDate和printDate函数,但是这两个函数中没有任何有关对象的说明,setDate和printDate函数如何知道打印的是哪个对象的数据呢?
所有的一切都需要this引用来解释。
2.3.4什么是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.month = month;
this.day = day;
}
public void printDate() {
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
注意:this引用的是调用成员方法的对象。
public static void main(String[] args) {
Date d = new Date();
d.setDay(2020,9,15);
d.printDate();
}
2.3.5this引用的特性
1.this的类型:对应类型类型引用,即哪个对象调用就是哪个对象的引用类型
2.this只能在成员方法中使用
3.在成员方法中,this只能引用当前对象,不能再引用其他对象
4.this是成员方法第一个隐藏参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责接收。
在代码层面来简单演示一下(下面右侧中的Date类也是可以通过编译的)
3.对象的构造和实例化
3.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方法才可以将具体的日期设置到对象中。
4.构造方法
4.1概念
构造方法(构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
public class Date {
public int year;
public int month;
public int day;
// 构造方法:
// 名字与类名相同,没有返回值类型,设置为void也不行
// 一般情况下使用public修饰
// 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
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) {
// 此处创建了一个Date类型的对象,并没有显式调用构造方法
Date d = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
d.printDate(); // 2021-6-9
}
}
需要注意的是:构造方法的作用就是对对象中的成员进行初始化,并不负责开辟空间
4.2特性
- 名字必须与类名相同
- 没有返回值类型,设置void也不行
- 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
- 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
public class Date {
public int year;
public int month;
public int day;
// 无参构造方法
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;
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
Date d = new Date();
d.printDate();
}
}
上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载,
5.如果说用户没有显示定义,编译器会生成一份默认的构造方法,生成默认构造方法一定是无参的。
public class Date {
public int year;
public int month;
public int day;
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
Date d = new Date();
d.printDate();
}
}
上述Date类中,没有定义任何构造方法,编译器会默认生成一个不带参数的构造方法。
注意:用户一旦定义,编译器则不再生成。
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 void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
// 如果编译器会生成,则生成的构造方法一定是无参的
// 则此处创建对象是可以通过编译的
// 但实际情况是:编译期报错
Date d = new Date();
d.printDate();
}
}
/*
Error:(26, 18) java: 无法将类 extend01.Date中的构造器 Date应用到给定类型;
需要: int,int,int
找到: 没有参数
原因: 实际参数列表和形式参数列表长度不同
*/
6.构造方法中,可以通过this调用其他构造方法来简化代码。
public class Date {
public int year;
public int month;
public int day;
// 无参构造方法--内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复
// 此处可以在无参构造方法中通过this调用带有三个参数的构造方法
// 但是this(1900,1,1);必须是构造方法中第一条语句
public Date() {
//System.out.println(year); 注释取消掉,编译会失败
this(1900, 1, 1);
//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;
}
}
注意:this(……)必须是构造方法中的第一句,也不能形成环。
public Date() {
this(1900,1,1);
}
public Date(int year, int month, int day) {
this();
}
/*
无参构造器调用三个参数的构造器,而三个参数构造器有调用无参的构造器,形成构造器的递归调用
编译报错:Error:(19, 12) java: 递归构造器调用
*/
7.绝大多数情况下使用public来修饰,特殊场景下会被private修饰
5.默认初始化
我们发现了一个问题,成员变量在定义时,并没有给初始值,为什么可以使用呢?
这就需要我们知道,在这个过程中,new关键字背后所发生的一些事情了。
Date d=new Date(2060,7,5);
在程序层面只是简单的一条语句,在JVM层面需要做很多事情,下面简单介绍一下:
1.检测对象对应的类是否加载了,如果没有就会加载
2.为对象分配内存空间
3.处理并发安全问题
比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突。
4.初始化所分配的空间
即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:
5.设置对象头信息
6.调用构造方法,给对象中各个成员赋值
6.就地初始化
即在声明成员变量时,就直接给出了初始值。
public class Date {
public int year = 1900;
public int month = 1;
public int day = 1;
public Date(){
}
public Date(int year, int month, int day) {
}
public static void main(String[] args) {
Date d1 = new Date(2021,6,9);
Date d2 = new Date();
}
}
注意:代码编译完成后,编译器会将所有成员给初始化的这些语句会添加到各个构造函数中。