目录
问题2:同样都是调用类中的方法,date1,date2,有什么不同呢?如何知道是对哪个对象进行操作实现?
面向对象
java是一门面向对象的语言,那什么是面向对象,我们直接进入主题
举一个栗子,正常洗衣服过程需要一下过程
而这些过程少一步都完成不了这个洗衣服这件任务
然而当我们有了对象就可以让对象来洗,当然这个对象并不是真的对象,在java中叫object,按上面的例子来阐述对象
我们将以上的程序流程可以变为四个对象,人,衣服,洗衣粉,洗衣机。
我们可以通过人,来操作衣服,洗衣粉,放到洗衣机里,在洗衣机中来完成洗衣服这个任务,而不需要去关心洗衣机是如何运行的,对于第一种方法来说不同衣服洗的方式,时间长度,拧干方式都不同,处理起来就比较麻烦。如果将来要洗鞋子,那就是另 一种放方式。 按照第二种方式来写代码,将来扩展或者维护起来会比较容易。
类与对象
认识对象后那么我们该怎样去创建一个对象,这时我们就需要认识一下类,概括来说,类是对象的模板,对象是类的实例,在以下例子中我们阐述创建了一个“PetDog”的对象,对于宠物狗来说,会有不同的名字,颜色,品种和动作,那么对于不同的宠物狗来说就是一个类
class PetDog {
public String name;//名字
public String color;//颜色
// 狗的属性
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
// 狗的行为
public void wag() {
System.out.println(name + ": 摇尾巴~~~");
}
}
类的定义
类中包含有属性(成员变量,在类的内部成员方法的外部)与对应的功能(成员方法)
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类 具有哪些功能,称为类的成员方法。
class为定义类的关键字,class后紧接着是类的名字,{}中为类的主体。
类的实例化
定义了一个类,就相当于在计算机中定义了一种新的类型,就如在int,double 等类型一样,可以通过他们来创建一个变量,而int,double 等是有java中的内置类型,而类是用户自定义了一个新的类型,用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。
现在我们有了类,便可以通过类来创建一个真正的对象
public class Main{
public static void main(String[] args) {
PetDog dogh = new PetDog(); //通过new实例化对象
dogh.name = "阿黄";
dogh.color = "黑黄";
dogh.barks();
dogh.wag();
PetDog dogs = new PetDog();
dogs.name = "赛虎";
dogs.color = "棕色";
dogs.barks();
dogs.wag();
}
}
输出结果:
阿黄: 旺旺旺~~~
阿黄: 摇尾巴~~~
赛虎: 旺旺旺~~~
赛虎: 摇尾巴~~~
- new 关键字用于创建一个对象的实例
- 使用 . 来访问对象中的属性和方法
- 同一个类可以创建多个实例
讨论
- 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员
- 类是一种自定义的类型,可以用来定义变量
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量,而类相当于图纸,在没有实例化,并没有实际存在
this引用
为什么要有this引用
以下举例子说明(创建一个日期类,并对其进行实例化)
//创建日期类
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 printDay() {
System.out.println(year+"/"+month+"/"+day);
}
}
//在主函数中去实例化
public static void main(String[] args) {
Date date1 = new Date();//new一个date1对象
Date date2 = new Date();//new一个date2对象
//分别进行初始化
date1.setDay(2022,11,8);
date2.setDay(2022,11,9);
//打印
date1.printDay();
date2.printDay();
}
问题1:参数名与变量名如果不小心相同
public void setDay(int year, int month, int day){
year = year;
month = month;
day = day;
}
那函数体中到底是谁给谁赋值?成员变量给成员变量?参数给参数?参数给成员变量?成员变量参数?
问题2:同样都是调用类中的方法,date1,date2,有什么不同呢?如何知道是对哪个对象进行操作实现?
什么是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(在此不做赘述)
this引用的特性
- this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
- this只能在”成员方法”中使用
- 在”成员方法”中,this只能引用当前对象,不能再引用其他对象
- this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法 对象的引用传递给该成员方法,this负责来接收
对象的构造及初始化
在上篇文章中介绍了java中的数据类型必须要初始化,否则会报错,那么对于创建的类该如何进行对象的初始化
在上述日期类中,我们采用了类中的成员方法SetDate来对对象进行初始化,但是每次对象创建好后调用SetDate方法设置具体日期,比较麻烦,那对象该如何初始化?
构造方法
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且 在整个对象的生命周期内只调用一次。
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被调用了");
}
public void printDate(){
System.out.println(year + "/" + month + "/" + day);
}
public static void main(String[] args) {
// 此处创建了一个Date类型的对象,并没有显式调用构造方法
Date d = new Date(2022,11,9); // 输出构造方法Date被调用了
d.printDate(); // 2022/11/9
}
}
特性
- 名字必须与类名相同
- 没有返回值类型,设置为void也不行
- 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
- 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
- 如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的 注意:一旦用户定义,编译器则不再生成
- 构造方法中,可以通过this调用其他构造方法来简化代码
- 绝大多数情况下使用public来修饰,特殊场景下会被private修饰(在此不做阐述)
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: 递归构造器调用
*/
默认初始化
在上面的例子中我们可以发现一个问题,为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?
public class Date {
public int year;
public int month;
public int day;
public Date(int year, int month, int day) {
// 成员变量在定义时,并没有给初始值, 为什么就可以使用呢?
System.out.println(this.year);
System.out.println(this.month);
System.out.println(this.day);
}
public static void main(String[] args) {
// 此处a没有初始化,编译时报错:
// Error:(24, 28) java: 可能尚未初始化变量a
// int a;
// System.out.println(a);
Date d = new Date(2021,6,9);
}
}
要搞清楚这个过程,就需要知道 new 关键字背后所发生的一些事情:
在new的时候JVM在层面需要做很多东西
- 检测对象对应的类是否加载了,如果没有加载则加载
- 为对象分配内存空间
- 处理并发安全问题 比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突 数据类型 默认值 byte 0 char ‘\u0000’ short 0 int 0 long 0L boolean false float 0.0f double 0.0 reference null
- 初始化所分配的空间 即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值
- 设置对象头信息
在此不做过多得介绍,简单了解
以上就是本文的全部内容,如果对你有帮助的话,期待你的点赞加关注!