目录
前言
今天我们将进入到类和对象的内容,所谓类和对象是学习Java中非常重要的一章内容,我们必须掌握好本节内容,才能更好的应用Java的相关技术。
一、 面向对象的初步认知
1.1 什么是面向对象
解释:
Java 是一门纯面向对象((Object Oriented Program,OOP)的语言,
但是不是说面向对象的语言只有 Java;
在面向对象的世界里,一切皆为对象;
面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。
1.2 面向对象 与 面向过程
1.2.1 面向过程
实例分析:
注重的是洗衣服的过程,少了一个环节可能都不行。
而且不同衣服洗的方式,时间长度,拧干方式都不同,处理起来就比较麻烦。
如果将来要洗鞋子,那就是另一种放方式。
如果按照这种 面向过程 的方式写代码,将来扩展或者维护起来会比较麻烦。
1.2.2 面向对象
实例分析:
以面向对象方式来进行处理,就不关注洗衣服的过程;
具体洗衣机是怎么来洗衣服,如何来甩干的,用户不用去关心,只需要将衣服放进洗衣机,导入洗
衣粉,启动开关即可,
通过对象之间的交互来完成的。
总之,面向过程 的意思 就是 所有的过程 都要一步一步的自己去实现;而 面向对象 的意思是 需要去 找对象、创建对象、使用对象,不注意其中的过程。
注意:
面向过程和面向对象并不是一门语言,而是解决问题的方法,没有那个好坏之分,都有其专门的应用场景
1.2.3 对象从何而来
想要有一个对象,首先就需要有一个类;
认为某一个实物(人、衣服、洗衣机、动物等等)是一个对象,那么就得需要去创建一个类;
有了类以后,就可以有对象了。
二、 类的定义与使用
2.1 简单认识类
类,就相当于一个 理论上的东西;
而 对象,就是把这个理论化的东西 给 造出来到现实世界之中。
举个例子,想要建造一个房子;那么,房子的图纸 就是一个 类;而 造出来的房子 就是一个对象。
2.2 类的定义格式
在java中定义类时需要用到class关键字,具体定义语法如下:
解析:
其中,class为定义类的关键字,ClassName为类的名字,需要用大驼峰的形式命名,{}中为类的主体。
类中包含的内容称为类的成员。
属性主要是用来描述类的,称之为类的成员属性或者类成员变量。
方法主要说明类具有哪些功能,称为类的成员方法。
代码示例:
public class Person {
//属性【成员变量】:定义在类当中,并且在方法的外边
public String name;
public int age;
//方法【成员方法】
public void sleep(){
System.out.println("睡觉!!!!!!");
}
public void eat(){
System.out.println("吃饭!!!!!!");
}
public void show(){
System.out.println("姓名:"+name+"年龄:"+age);
}
}
【说明】定义了一个 Person类,就相当于有了一个 模板 了;通过模板可以造出不同的对象,比如说,小明有自己的 name,age,也会sleep,eat,show;小花也有自己的 name,age,也会sleep,eat,show
需要注意的是,一个 .java文件 只能有一个public类,如果有多个的话,那么就会报错:
【注意】:
一般一个 .java文件 当中只定义一个类(这个不是硬性要求);
main方法所在的类一般要使用public修饰(当然,如果不是public类也可以修饰main方法);
![]()
3.public修饰的类必须要和文件名相同,否则就会报错;
4.不要轻易去修改public修饰的类的名称,如果要修改,通过开发工具修改;
三、 类的实例化
3.1 什么是实例化
定义了一个类,就相当于在计算机中定义了一种新的类型;
与int,double类似,只不过int和double是java语言自带的内置类型,而类是用户自定义了一个新的类型,比如上述的:Person类(一种新定义的类型);
有了自定义的类型之后,就可以使用这些类来定义实例(或者称为对象)。
用类类型创建对象的过程,称为类的实例化,在java中采用new 关键字,配合 类名 来实例化对象。
代码示例:
首先创建一个Person类(用来找对象,相当于一个图纸):
public class Person {
//属性:成员变量——>定义在 类的内部,方法的外部
public String name;
public int age;
public void sleep(){
System.out.println("睡觉!!!!!!");
}
public void eat(){
System.out.println("吃饭!!!!!!");
}
public void show(){
System.out.println("姓名:"+name+"年龄:"+age);
}
}
然后在另外一个类上面 通过new关键字 来实例化对象(用来创建对象,通过图纸来建造房子):
public class TestDemo_2 {
public static void main(String[] args) {
//通过new关键字来实例化对象
//可以实例化多个对象
//创建的对象都有类中的属性
Person person1 = new Person();
Person person2 = new Person();
Person person3 = new Person();
Person person4 = new Person();
}
}
new关键字的语法格式:
类名 变量名 = new 类名(); //调用方法的时候才会用小括号(),其实这个也是调用方法——>构造方法 //至于什么是构造方法,以及构造方法的相关知识点,会在下面介绍
这个过程叫做 实例化对象,它是一个创建对象的过程,只要new 就会给这块对象分配一块内存。不要说 成员变量就是对象!!!!!!
属性:又称作 成员变量(定义在类的内部,方法的外部的)。
new了一个对象以后,在对象里面 就会拥有 这些属性:
那么我们怎么才能调用这些对象呢(使用对象)?
这个时候就需要用到 点操作符 .
此时,如果运行以下代码,堆上的对象就会被赋予相应的初值:
当然,我们也可以通过 点操作符 . 来调用相应的方法:
//Person类 public class Person { public String name; public int age; public void sleep(){ System.out.println("睡觉!!!!!!"); } public void eat(){ System.out.println("吃饭!!!!!!"); } public void show(){ System.out.println("姓名:"+name+" 年龄:"+age); } }
//测试类 public class TestDemo { public static void main(String[] args) { Person person1 = new Person(); person1.name = "zhangsan"; person1.age = 19; person1.eat(); person1.sleep(); person1.show(); System.out.println("----------------------------------"); Person person2 = new Person(); person2.name = "lisi"; person2.age = 20; person2.eat(); person2.sleep(); person2.show(); } }
代码运行结果:
当然,如果成员变量在刚开始的时候没有赋予初值,那么就会默认为初始值是对应的0值;
如果是局部变量的话,在前面介绍过,如果局部变量没有初始化,那么肯定会报错。
代码运行:
3.2 总结出三个小问题
3.2.1 如何定义一个类
public class Student {
//属性
public String name;
public int age;
public double score;
public String sex;
//方法
public void doClass(){
System.out.println("上课!!!!!!");
}
public void doHomeWork(){
System.out.println("做作业!!!!!!");
}
}
3.2.2 如何通过这个类 实例化对象
Student student1 = new Student();
Student student2 = new Student();
3.2.3 怎么去访问实例化出来的 对象的属性和方法
//通过对象的引用
student1.属性;
student1.方法;
四、this引用
4.1 为什么要有this引用
举例说明:
现在我们先来看一个日期类的例子:
public class MyDate {
public int year;
public int month;
public int day;
/**
* 设置日期
*/
public void setDate(int myYear,int myMonth,int myDay){
year = myYear;
month = myMonth;
day = myDay;
}
/**
* 打印日期
*/
public void printDate(){
System.out.println("年:"+year+" 月:"+month+" 日:"+day);
}
public static void main(String[] args) {
MyDate myDate1 = new MyDate();
myDate1.setDate(2022,3,27);
myDate1.printDate();
MyDate myDate2 = new MyDate();
myDate2.setDate(2022,3,27);
myDate2.printDate();
}
}
代码输出结果:
解释:
以上代码结构非常简单,就是定义了一个日期类,然后并且对这个日期类进行打印。
看起来确实是没有什么问题,但是仔细琢磨琢磨还是有问题的:
第一个问题:站在setDate方法的角度来说,不知道 year是哪个对象的year,month是哪个对象的month,day是哪个对象的day(因为现在有两个对象);
第二个问题:当把setDate方法改成这个样子的时候,按理来说也是正确的,没有任何的逻辑错误;但是当真正运行的时候,就会发现运行结果出现偏差:
/** * 设置日期 */ public void setDate(int year,int month,int day){ year = year; month = month; day = day; }
代码结果:
其实是这样子出现偏差的:
上面的 year = year;month = monrh;day = day; 其实是一样的。
传的参数year、month、day它们是局部变量,其作用域在setDate方法内部;
即:在作用域范围内,其出现的所有year、month、day其实都是形参的year、month、day;
就相当于 是自己给自己赋值了,但是没有给 上面的 处于setDate方法之外的 局部范围之外的 当前对象的year、month、day赋值;
所以,存储在堆上面的 对象的 year、month、day并没有被赋值;
所以就会产生偏差,这个很好理解。
4.2 this的引用
那么,应该怎样去解决上面的问题呢?
这个就需要 this引用 来解决这个问题:
/** * 设置日期 */ public void setDate(int year,int month,int day){ this.year = year; this.month = month; this.day = day; }
输出结果:
通过使用 this引用,又正确的打印出来了。
4.3 this的引用特性
this:代表当前对象的引用,即 哪个对象调用就是哪个对象的引用类型。这个可以用打断点的方式来证明:
到目前为止,我们知道 关于this的特性:
- 代表当前对象的引用;
- 当参数和成员的名字冲突的时候,可以用以区别(当然,如果名字不冲突的时候,也可以用this.);
到底以后的程序是否要加上this?
建议是:在当前类当中去访问 自己的成员变量和属性的时候,可以去把this加上(不是硬性要求),如:
/**
* 设置日期
*/
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);
}
注意:
当然,1.this只能 在 "成员方法" 中使用,this不能再静态方法里面使用(这个在下面会介绍)。
2.在"成员方法"中,this只能引用当前对象,不能再引用其他对象,具有final属性。
五、对象的构造及初始化
5.1 如何去初始化对象
通过前面知识点的学习知道,在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。
代码解析:
如果想要去初始化对象,那么可以用 点操作符. 去一个一个初始化;
也可以去调用所创建的方法去初始化对象:
点操作符.
调用所创建的方法去初始化对象:
还有一种初始化的方式——就地初始化:即直接在所定义的 属性 进行赋值:
不过这种方式一点也不好,毕竟这个Student类是一个模板;
不可能以后所实例化的对象 都叫做 bit,年龄都是19岁......
那么如果有的学生 不叫做 bit,年龄不是19岁,......,那么在实例化过后 又需要重新进行赋值,就会把 就地初始化 所附的值给覆盖掉了;那么,在平常的情况下就显得没有必要了,除非业务需求希望是 默认就要那些属性值。
当然,初始化对象不可能只有这几种方式,还可以有我们下面所介绍的 构造方法:
5.2 构造方法
5.2.1 概念
构造方法(也称为构造器)是一个特殊的成员方法;
要求:
- 方法名必须和类名是一致的;
- 没有返回值。
【说明】在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
【注意】
当我们实例化一个对象的时候,必须会经过以下两个步骤(但不是一定只有这两个步骤):
- 为对象分配内存;
- 调用合适的构造方法。
代码举例:
下面我们来看一下例子来介绍:
代码解析:实际上,在实例化对象的时候,它会默认调用 构造方法;
//一开始就在疑惑,一般 方法的后面才会有小括号, //为什么 实例化对象的时候 会有小括号()的出现呢? Student student = new Student(); //原来这个小括号就是 在默认帮助调用构造方法
//一开始就在疑惑,一般 方法的后面才会有小括号,
//为什么 实例化对象的时候 会有小括号()的出现呢?
//原来这个小括号就是 在默认帮助调用构造方法
那么,现在 又有人会发出疑惑,一开始的时候不是没有写 构造方法吗,为什么程序却没有报错呢?
其实,当程序当中 没有构造方法的时候,编译器会帮助我们 默认提供一个不带参数的构造方法,
即:没有构造方法的时候,它会默认提供一个如下的默认构造方法:
如果写上了一个构造方法,那么编译器就不会再帮你默认生成一个不带参数的构造方法:
细心的铁汁们就会发现,构造方法是可以发生重载的;
在实例化对象的时候调用构造方法;
那么,用 构造方法 来干嘛呢?
——可以用来帮助初始化当前对象的属性:
这样就不需要一个一个的去赋值了,直接new对象的时候去赋值就可以了:
当然,可以用IDEA来 自动提供包含参数的构造方法(就是可以不用自己来写了):
5.2.2 特性
1.名字必须与类名相同 ;
2.没有返回值类型,设置为void也不行;
3.创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次);
4.构造方法可以重载 (用户根据自己的需求提供不同参数的构造方法) 。
5.如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。
6.this可以用来调用 本类中其他的构造方法。
浅浅的总结一下:
1.构造方法 是没有返回值的方法,方法名和类名是一样的;
2.构造方法 不止一个,可以有多个,多个构造方法之间,构成了重载;
3.当我们写了一个类之后,没有写构造方法的时候,编译器会帮助我们 默认生成一个不带参数的构造方法;
4.当我们写了任何一个构造方法之后,编译器不再为我们,提供不带参数的构造方法;
5.一个类 至少会有1个构造方法 就算你没有写;
6.构造方法 本质 就是来实例化对象的时候调用的,可用于初始化属性;
7.this可以用来调用 本类中其他的构造方法【要在构造方法当中使用】(就是调用方法,不过有一个非常大的前提:必须要把this放到第一行,否则就会报错);所以,只能在构造方法当中,只能调用一个:
代码:
public class Student {
public String name;
public int age;
public double score;
public String sex;
public void show(){
System.out.println("姓名:"+name+" 年龄:"+age+" 学分:"+score+" 性别:"+sex);
}
public Student(){
this("张三",19,100,"男");
System.out.println("这个是不带参数的构造方法!!!!!!");
}
public Student(String name,int age,double score,String sex){
this.name = name;
this.age = age;
this.score = score;
this.sex = sex;
System.out.println("这个是带4个参数的构造方法!!!!!!");
}
//测试
public static void main(String[] args) {
Student student = new Student();
student.show();
}
}
运行结果:
this可以访问属性,this可以访问构造方法,那么this还可以 在一个普通的成员方法当中,通过this来调用另一个成员方法(当然,不加上this也可以,加上this更可以,习惯上还是来加一下):
8.this的用法:
①this.data; 访问属性
②this.func(); 访问方法
③this(); 调用本类中其他的构造方法
9.不能形成环:
5.3 就地初始化 和 默认初始化
5.3.1 就地初始化
就地初始化 定义就是:在声明成员变量时,就直接给出了初始值。
public class Student {
public String name = "张三";
public int age = 19;
public double score = 100;
public String sex = "男";
}
5.3.2 默认初始化
默认初始化 定义就是:在声明成员变量时,没有给出初始值(但默认给出的是各种类型所对应的0值)。
public class Student {
public String name;
public int age;
public double score;
public String sex;
}
类和对象(2)持续更新中ing
总结
类和对象(2)持续更新中ing