目录
1.目标:理解类和对象之间的关系
Java中一切皆为对象,比如描述一个人,会从他的长相和他所能做的事情来进行。
而对象的属性和对象的行为就构成了类。
2. 面向对象的初步认知
2.1 什么是面向对象
Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。
2.2 面向对象与面向过程
我们所学的c语言就是一种面向过程的编程语言。就一个洗衣服的例子来说。传统的洗衣服过程是要分很多很多步来执行。
而面向过程则是只关心对象,不关心过程。整个洗衣服的过程:人将衣服倒进洗衣机,倒入洗衣粉,洗衣机启动,最后甩干衣服。这个过程包含了:人,洗衣机,洗衣粉,衣服四个对象。人们不需要去了解洗衣机具体是怎么工作的。只要了解对象之间是如何交互的即可。
3.类的定义和使用
类是用来对一个实体(对象)来进行描述的,比如:洗衣机,它是一个品牌,在Java中可以将其看成是一个类别。
属性:产品品牌,型号,产品重量,外观尺寸,颜色...
功能:洗衣,烘干、定时...
3.1 类的定义格式
// 创建类
class ClassName{
field; // 字段(属性) 或者 成员变量
method; // 行为 或者 成员方法
}
class为定义类的关键字,ClassName(注意类名最好采用大坨峰的形式)为类的名字,{}中为类的主体。
例如:定义一个洗衣机类
class WashMachine{
public String brand; // 品牌
public String type; // 型号
public double weight; // 重量
public double length; // 长
public double width; // 宽
public double height; // 高
public String color; // 颜色
public void washClothes(){ // 洗衣服
System.out.println("洗衣功能");
}
public void dryClothes(){ // 脱水
System.out.println("脱水功能");
}
public void setTime(){ // 定时
System.out.println("定时功能");
}
}
一个类对应一个字节码文件,一般情况下,一个Java文件对应一个类。
那怎么样在IDEA中打开java文件呢?
4.类的实例化
4.1 什么是实例化
定义了一个类,就相当于在计算机中定义了一种新的类型,与int,double类似,只不过int和double是java语言自带的内置类型,而类是用户自定义了一个新的类型,比如上述的洗衣机类(一种新定义的类型)有了自定义的类型之后,就可以使用这些类来定义实例(或者称为对象)。用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。
这样就实例化出了三个对象。
new对象的过程中,其实Java也进行了内存分配。我们的对象是在堆区上,只是将对象的地址给了引用变量,washMachine1就是一个引用变量,上面代码代表,我通过类定义了一个引用变量。这个引用变量指向了那个对象,也叫做引用指向对象。
这里就只画了两个对象作为实例。
class WashMachine{
public String brand; // 品牌
public String type; // 型号
public double weight; // 重量
public double length; // 长
public double width; // 宽
public double height;// 高
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 washMachine1 = new WashMachine();
washMachine1.dryClothes();
washMachine1.setTime();
washMachine1.washClothes();
}
}
由此我们可以看出:
new 关键字用于创建一个对象的实例.
使用 . 来访问对象中的属性和方法.
同一个类可以创建多个实例.
5.this引用
5.1 为什么要有this引用
先看一个日期类的例子:
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. 形参名不小心与成员变量名相同:
此时,编译器输出的结果是
这是因为
2.三个对象都在调用setDate和printDate方法,但是这两个方法中没有任何有关对象的说明,setDate和printDate方法如何知道打印的是那个对象的数据呢?
这一切就要用this来解释了。
5.2 什么是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引用代表的是当前对象的引用, this只能在"成员方法"中使用
public static void main(String[] args) {
Date d = new Date();
d.setDay(2020,9,15);
d.printDate();
}
有的人可能说this引加不加上都不影响结果,我的建议是最好加上,加上有不会错,还能让代码更加具有可读性。
6. 对象的构造及初始化
6.1 如何初始化对象
通过前面知识点的学习知道,在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。
public static void main(String[] args) {
int a;
System.out.println(a);
}
// Error:(26, 28) java: 可能尚未初始化变量a
要让上述代码通过编译,非常简单,只需在正式使用a之前,给a设置一个初始值即可。如果是对象:
public static void main(String[] args) {
Date d = new Date();
d.printDate();
d.setDate(2021,6,9);
d.printDate();
}
// 代码可以正常通过编译
需要调用之前写的SetDate方法才可以将具体的日期设置到对象中。通过上述例子发现两个问题:
1. 每次对象创建好后调用SetDate方法设置具体日期,比较麻烦,那对象该如何初始化?
2. 局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?
6.2 构造方法
6.2.1 概念
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
6.2.2 特性
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 Date() {
System.out.println("abcdef");
}
public static void main(String[] args) {
// 构造三个日期类型的对象 d1 d2 d3
Date d = new Date();
d.printDate();
}
}
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 Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("调用三个参数的构造方法!");
}
public Date() {
System.out.println("abcdef");
}
public static void main(String[] args) {
Date d = new Date(2023,6,23);
d.printDate();
}
}
这样,我们就能够得出构造方法的一些特点
1. 名字必须与类名相同
2. 没有返回值类型,设置为void也不行
3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
4. 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
5.构造方法中,可以通过this调用其他构造方法来简化代码
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 Date() {
this(2023,1,23);
System.out.println("不带参数的构造方法!");
}
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("调用三个参数的构造方法!");
}
public static void main(String[] args) {
Date d = new Date();
d.printDate();
}
}
注意:this(...)必须是构造方法中第一条语句
this(...)不能形成环
public Date(){
this(1900,1,1);
}
public Date(int year, int month, int day) {
this();
}
/*
无参构造器调用三个参数的构造器,而三个参数构造器有调用无参的构造器,形成构造器的递归调用
编译报错:Error:(19, 12) java: 递归构造器调用
*/
总结一下:this()调用:1. 这个写法只能写在构造方法中
2. 构造方法中,不能自己调用自己
3. 它只能够放在构造方法的第一行
6.3 默认初始化
在上文中提出的第二个问题:为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?
这个留在后续的章节中讲解,我们只要知道默认的值是多少就行了
6.4 就地初始化
很简单,在声明成员变量时,就直接给出了初始值
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();
}
}