三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Java入门9 类和对象

Java入门9 类和对象

1. 面向对象的初步认知

1.1 什么是面向对象

Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成⼀件事情。用面向对象的思想来设计程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。

1.2 面向对象与面向过程

传统洗衣服过程

传统的方式:注重的是洗衣服的过程,少了一个环节可能都不行。 而且不同衣服洗的方式,时间长度,拧干方式都不同,处理起来就比较麻烦。如果将来要洗鞋子,那 就是另⼀种方式。 按照该种方式来写代码,将来扩展或者维护起来会比较麻烦。

现代洗衣服过程

以面向对象方式来进行处理,就不关注洗衣服的过程,具体洗衣机是怎么来洗衣服,如何来甩干的,用户不用去关心,只需要将衣服放进洗衣机,倒⼊洗衣粉,启动开关即可,通过对象之间的交互来完成的。
注意:面向过程和面向对象并不是一门语言,而是解决问题的方法,没有那个好坏之分,都有其专门的应用场景。

2. 类定义和使用

面相对象程序设计关注的是对象,而对象是现实生活中的实体,比如:洗衣机。但是洗衣机计算机并不认识,需要开发人员告诉给计算机什么是洗衣机。

上图左侧就是对洗衣机简单的描述,该过程称为对洗衣机对象(实体)进行抽象(对一个复杂事物的重新认知),但是这些简化的抽象结果计算机也不能识别,开发人员可以采用某种面相对象的编程语言来进行描述,比如:Java语言。

2.1 简单认识类

类是用来对⼀个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了。
比如:洗衣机,它是⼀个品牌,在Java中可以将其看成是⼀个类别。
属性:产品品牌,型号,产品重量,外观尺存,颜色...
功能:洗衣,烘干、定时....
在Java语言中,如何对上述的洗衣机类来进行定义呢?

2.2 类的定义格式

在Java中定义类时需要用到class关键字,具体语法如下:

class ClassName{ //创建类 friend; //属性或成员变量 method; //行为或成员方法 }

class为定义类的关键字,ClassName为类的名字,{}中为类的主体。类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法

采用Java语言将洗衣机类在计算机中定义完成,经过javac编译之后形成.class文件,在JVM的基础上计算机就可以识别了。

注意事项
• 类名注意采用大驼峰定义
• 成员前写法统⼀为public,后面会详细解释
• 此处写的方法不带static关键字.后面会详细解释

2.3 练习

• 定义一个Dog类,大家可以思考一下,哪些是Dog的属性?哪些是Dog的行为?
参考代码如下:

• 定义⼀个学生类Student,大家可以思考一下,哪些是Student的属性?哪些是Student的行为?
参考代码如下:

注意事项:
1. 一般一个文件当中只定义一个类
2. public修饰的类必须要和文件名相同
3. 不要轻易去修改public修饰的类的名称,如果要修改,通过开发工具修改

3. 类的实例化

3.1 什么是实例化

定义了一个类,就相当于在计算机中定义了一种新的类型,与int,double类似,只不过int和double
是java语言自带的内置类型,而类是用户自定义了⼀个新的类型,比如上述的:PetDog类和Student类。它们都是类(⼀种新定义的类型)有了这些⾃定义的类型之后,就可以使用这些类来定义实例(或者称为对象)。
用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。

3.2 如何访问对象当中的成员

注意事项:

• new关键字用于创建一个对象的实例.

• 使用来访问对象中的属性和方法.

• 同一个类可以创建多个实例.

3.3 类和对象的再次理解


1.只是一个模型⼀样的东西,用来对⼀个实体进行描述,限定了类有哪些成员.
2.类是⼀种自定义的类型,可以用来定义变量.

3. ⼀个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量
4. 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是⼀个设计,实例化出的对象才能实际存储数据,占用物理空间。

4. this关键字

4.1 为什么要有this引用

如下代码定义了一个Date类,Date类中包含3个属性分别是year,month,day。分别使用setDay和 printDate对进行设置和打印日期。

提出2个疑问
1. 形参名不小心与成员变量名相同,会发生什么?

public void setDay(int year, int month, int day){ year = year; month = month; day = day; }

首先要搞清楚括号里的year,month,day都是形参,需要接收新的数据来填充。而类中方法外的year,month,day则是成员变量,成员变量有对应的默认值比如当前三个属性都是int类型所以成员变量默认值都是0,我们现在的目的就是想成员变量year = 形参接收到的year,如果没有this关键字Java程序就会优先把左右两边同名的year,month,day都当成形参,就会变成形参year = 形参year,这样我们的成员变量就没有改变还是默认值0,无法达到我们的目的。而this关键字就是将左边同名的year,month,day都标明是成员变量,这样就可以解决同名导致的问题。

4.2 this是什么


this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

此时通过指定this,就能正确解决上述的2个问题了。这里之所以可以起作用,关键点在于this代表的是当前对象的引用,当前对象就是指:哪个对象调用setDay2方法,谁就是this引用!

4.3 this引用的特性


1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
2. this只能在"成员方法"中使用

3. 在"成员方法"(非静态成员方法)中,this只能引用当前对象,不能再引用其他对象
4. this是“成员方法”第⼀个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将
调用成员方法对象的引用传递给该成员方法,this负责来接收

5. this的使用总结

this.成员变量 //访问对象的成员变量 this.成员方法 //访问对象的成员方法

事实上,我们也可以通过this来访问构造方法,那么什么是构造方法呢?

5. 对象的构造及初始化

5.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. 局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?

5.2 默认初始化

public class Date { public int year; public int month; public int day; public static void main(String[] args) { // 此处a没有初始化,编译时报错: // Error:(24, 28) java: 可能尚未初始化变量a // int a; // System.out.println(a); Date d = new Date(); System.out.println(d.year); System.out.println(d.month); System.out.println(d.day); } }

对于成员变量来说,如果没有进行初始化,会有一个对应的默认值,默认值遵循如下规则:

5.3 就地初始化

在声明成员变量时,就直接给出了初始值。

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(); } }

5.4 构造方法初始化


5.4.1 构造方法概念


构造方法(也称为构造器)是⼀个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。

5.4.2 构造方法注意事项


1. 名字必须与类名相同
2. 没有返回值类型,设置为void也不行
3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
4. 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)

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类中,没有定义任何构造方法,编译器会默认生成⼀个不带参数的构造方法。

6. 构造方法中,可以通过this调用其他构造方法来简化代码

public class Date { public int year; public int month; public int day; public Date(){ this(1900, 1, 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(); }

7. 绝大多数情况下使用public来修饰,特殊场景下会被private修饰(后序讲单例模式时会遇到)

6. 对象的打印


如果我们直接打印对象的引用,此时输出的结果为:类路径名@对象的hashcode值。

public class Person { String name; String gender; int age; public Person(String name, String gender, int age) { this.name = name; this.gender = gender; this.age = age; } public static void main(String[] args) { Person person = new Person("Jim","男", 18); System.out.println(person); } }

如果想要默认打印对象中的属性该如何处理呢?答案:重写toString方法即可

public class Person { String name; String gender; int age; public Person(String name, String gender, int age) { this.name = name; this.gender = gender; this.age = age; } @Override public String toString() { return "[" + name + "," + gender + "," + age + "]"; } public static void main(String[] args) { Person person = new Person("Jim","男", 18); System.out.println(person); } } // 输出结果:[Jim,男,18]
← 返回列表