文章目录
- 1. 面向对象的初步认知
- 1.1 什么是面向对象
- 1.2 面向对象与面向过程
- 2. 类的定义和使用
- 2.1 简单认识类
- 2.2 类的定义格式
- 3. 类的实例化
- 3.1 什么是实例化
- 3.2 类和对象的说明
- 4. this引用
- 4.1 为什么要有this引用
- 4.2 什么是this引用
- 4.3 this引用的特性
- 5. 对象的构造及初始化
- 5.1 构造方法
- 5.1.1 概念
- 5.1.2 特性
- 5.1.3 默认初始化
- 5.2 就地初始化
1. 面向对象的初步认知
1.1 什么是面向对象
Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,**一切皆为对象。**面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。
1.2 面向对象与面向过程
传统洗衣服(面向过程):
现代洗衣服(面向对象):
2. 类的定义和使用
2.1 简单认识类
类是用来对一个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了。
2.2 类的定义格式
在java中定义类时需要用到class关键字,具体语法如下:
// 创建类
class ClassName{field; // 字段(属性) 或者 成员变量 method; // 行为 或者 成员方法
}
class为定义类的关键字,ClassName为类的名字,{}中为类的主体。
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。
注意事项
- 类名注意采用大驼峰定义
- 成员前写法统一为public,后面会详细解释
- 此处写的方法不带 static 关键字. 后面会详细解释
- 一般一个文件当中只定义一个类
- main方法所在的类一般要使用public修饰(注意:Eclipse默认会在public修饰的类中找main方法)
- public修饰的类必须要和文件名相同
- 不要轻易去修改public修饰的类的名称,如果要修改,通过开发工具修改.
3. 类的实例化
3.1 什么是实例化
定义了一个类,就相当于在计算机中定义了一种新的类型,与int,double类似,只不过int和double是java语言自带的内置类型,而类是用户自定义了一个新的类型。类(一种新定义的类型),有了这些自定义的类型之后,就可以使用这些类来定义实例(或者称为对象)。
用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。
注意事项:
- new 关键字用于创建一个对象的实例.
- 使用 . 来访问对象中的属性和方法.
- 同一个类可以创建多个实例.注意事项:
- new 关键字用于创建一个对象的实例.
- 使用 . 来访问对象中的属性和方法.
- 同一个类可以创建多个实例.
public class Dog {public String name;public int age;public void eat(){System.out.println(name + "正在吃饭......");}
}
public class test {public static void main(String[] args) {Dog dog = new Dog();System.out.println(dog.name);// nullSystem.out.println(dog.age);// 0int a;System.out.println(a);// 报错}}
问题:局部变量在使用的时候要初始化。为什么在使用name和age的时候不报错,而使用a的时候却报错呢?
答:因为 name 和 age 是定义在类当中、方法外面的。它不是局部变量,它是成员变量,成员变量未初始化,它有一个默认值。
- 遵循规则:
- 引用类型默认为null.
- 基本数据类型默认为0
通过对象的引用 可以去访问 对象的成员变量和对象的成员方法。
- 可以通过关键字new可以实例化多个对象。
3.2 类和对象的说明
- 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员.
- 类是一种自定义的类型,可以用来定义变量.
- 一个类可以实例化出多个对象,实例化出的对象 才能占用实际的物理空间,存储类成员变量
4. this引用
4.1 为什么要有this引用
public static void main(String[] args) {Date date = new Date();date.setDate(2008, 8, 8);date.printDate();
}
public class Date {public int year;public int month;public int day;public void setDate(int y, int m, int d){year = y;month = m;day = d;}public void printDate(){System.out.println(year + "年" + month + "月" + day + "日");}
}
此时,程序输出结果为:2008年8月8日
我们通过调用 setDate() 方法对year、month、day都赋了值,所以我们调用printDate()方法时,就会打印2008年8月8日
但是接下来我们来看另一个代码:
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(2008, 8, 8);date.printDate();Date date2 = new Date();date2.setDate(2009, 9, 9);date2.printDate();Date date3 = new Date();date3.setDate(20010, 10, 10);date3.printDate();
}
程序输出结果:
0年0月0日
0年0月0日
0年0月0日
提出问题:
问题1:
这么多对象都调用了同一个setDate()方法,在这个方法内,它们是怎么区分是哪个对象调用的setDate()方法中的year、month、day。
问题2:
形参名和成员变量同名时,调用setDate()方法,却没有对year, month, day赋值。
答:在方法内,year, month, day都是局部变量。局部变量优先使用。
此时year = year; month = month; day = day;
,程序认为左边的 year, month, day 和右边的 year, month, day 都是形参自己,所以出现了形参自己给自己赋值的情况,却并没有修改到对象当中的 year, month, day 。而在打印时,我们打印的是成员变量,而我们的成员变量并没有成功被赋上值,所以就出现了打印出来都是0的情况。
问题2的解决方案就是加一个this.
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(this.year + "年" + this.month + "月" + this.day + "日");}
}
这样之后程序就能正常运行了。
4.2 什么是this引用
this就是代表当前对象的引用。 this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
哪个对象的引用 调用了 该方法 this就代表哪个对象。
问题:this是怎么传递的呢?
答:实际上它是隐藏的第一个参数,相当于public void setDate(Date this, int year, int month, int day){
, 这个参数可写可不写(一般情况下不写)。
习惯使用this!!!!
4.3 this引用的特性
- this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
- this只能在"成员方法"中使用,this不能在静态方法中使用,只能在非静态方法中使用。
- 在"成员方法"中,this只能引用当前对象,不能再引用其他对象
- this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收。
注意:下图右侧中的Date类也是可以通过编译的
this的用法有3种:
- 可以通过this访问 当前对象的成员变量。
- 可以通过this访问 当前对象的非静态的成员方法。
- 可以通过this访问 当前对象的其他构造方法。
5. 对象的构造及初始化
在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。
5.1 构造方法
一个对象的生成至少有两步:
- 为对象分配内存。
- 调用合适的构造方法(构造方法不止一个)。
构造方法的作用:对当前对象的成员进行初始化。
实例化对象的时候可以借用构造方法对对象进行初始化。
5.1.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}
}
注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。
构造方法快捷键:Alt + Insert
/ 鼠标右键–generate–Constructor
5.1.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();}
}
上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载。
- 当我们没有写任何的构造方法的时候, Java会提供一个默认的不带参数的构造方法。但是 一旦你有其他的构造方法, Java就不会再给你提供不带参数的构造方法了。
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
找到: 没有参数
原因: 实际参数列表和形式参数列表长度不同
*/
注意:
- this(…)必须是构造方法中第一条语句
- 绝大多数情况下使用public来修饰,特殊场景下会被private修饰
- 在实例化不同对象时,就可以根据不同的构造方法进行初始化。
5.1.3 默认初始化
源文件要想让编译器运行这个源文件,只能通过javac生成二进制的文件才能让编译器看懂,所以就生成了字节码文件,要把这个程序运行起来,一定会运行在JVM中,通过java命令会将字节码文件加载到JVM中,此时这字节码文件就会被JVM解析成Class对象(Java中一切皆对象)。
优点:之前被加载过的类,就不会再重复加载了。
5.2 就地初始化
在声明成员变量时,就直接给出了初始值。
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();}
}
注意:代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中