文章目录
类和对象
1、面向对象的初步认识
1.1什么是面向对象
Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。
2、类定义和使用
面相对象程序设计关注的是对象,而对象是现实生活中的实体,比如:洗衣机。但是洗衣机计算机并不认识,需要开发人员告诉给计算机什么是洗衣机。
上图就是对洗衣机简单的描述,该过程称为对洗衣机对象(实体)进行抽象(对一个复杂事物的重新认知),但是这些简化的抽象结果计算机也不能识别,开发人员可以采用某种面相对象的编程语言来进行描述,比如:Java语言。
2.1简单认识类
类是用来对一个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了。
比如:洗衣机,它是一个品牌,在Java中可以将其看成是一个类别。
属性:产品品牌,型号,产品重量,外观尺寸,颜色…
功能:洗衣,烘干、定时…
2.2类的定义格式
//类的名字采用大驼峰的形式,每个单词首字母字母大写
class ClassName{
field;//字段(或者叫属性,或者叫成员变量)
method;//行为或者成员方法
}
class为定义类的关键字,ClassName为类名,{ }中为类的主体
2.3定义一个类(一般情况下一个Java文件一个类,可以有多个)
每一个类对应一个字节码文件,下面的洗衣机类就会生成一个WashMachine.class的字节码文件定义一个洗衣机类
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语言将洗衣机类在计算机中定义完成,经过javac编译之后形成.class文件,在JVM的基础上计算机就可以识别了。
注意:
1、类目必须采用大驼峰形式
2、成员前写发统一为public
3、此处写的方法不带static关键字
4、方法名称都是小驼峰(第一个单词小写,后面的单词首字母都大写)
5、public修饰的类必须和文件名相同
6、main方法所在的类一般要用文件名修饰
3、类的实例化
3.1什么是实例化
定义了一个类,就相当于在计算机中定义了一种新的类型,与int,double类似,只不过int和double是java语言自带的内置类型,而类是用户自定义了一个新的类型,比如上述的:PetDog类和Student类。它们都是类(一种新定义的类型)有了这些自定义的类型之后,就可以使用这些类来定义实例(或者称为对象)。
用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。
public void washClothes(){
System.out.println("洗衣服");
}
public void dryClothes(){
System.out.println("脱水");
}
public void setTime(){
System.out.println("定时");
}
public class Class_And_Object{
public static void main(String[] args) {
//washMachine是一个引用变量,指向new WashMachine()这个对象,washMachine存的是new WashMachine()的地址
WashMachine washMachine1 = new WashMachine();
//类型WashMachine 定义了一个变量washMachine,赋值了一个new WashMachine()的值
//也就是说washMachine这个对象里有WashMachine这个类里的所有属性
washMachine1.brand = "格力";
System.out.println(washMachine1.brand);
WashMachine washMachine2 = new WashMachine();
washMachine2.brand = "小天鹅";
System.out.println(washMachine2.brand);
}
}
}
结论:可以使用new关键字实例化多个对象,多个对象之间互相不影响,因为他们都有一块儿独立的内存空间
class Person{
public String name;
public int age;
public void eat(){
System.out.println(name+"在吃饭");
}
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "张三";
person1.eat();//这个时候会输出张三在吃饭,调用eat的时候name已经被赋值了
}
}
3.2类和对象的说明
1、类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员.
2、类是一种自定义的类型,可以用来定义变量.
3、一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
4、做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
4、this引用
4.1为什么要有this引用
先看一个日期类
class TestDate
{
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+"日");
}
public static void main(String[] args)
{
TestDate testDate1=new TestDate();
TestDate testDate2=new TestDate();
TestDate testDate3=new TestDate();
testDate1.setDate(2022,5,11);
testDate2.setDate(2023,6,3);
testDate3.setDate(2024,10,18);
testDate1.printDate();
testDate2.printDate();
testDate3.printDate();
}
}
运行结果如下
问题来了:
问题1、setDate这个方法只有一个,我们赋值调用的时候怎么知道setDate调用的是对象testdata1的值,还是对象testdata2的值,有或者是testdata3的值呢
为了解决这个问题,这个时候我们就要使用this了
问题2:就是我们如果将上面的代码中setData方法中的形参变量名改成和对象中成员名相同的话就会出现问题如图所示
public void setDate(int year,int month,int day)
{
year=year;
month=month;
day=day;
}
其他的代码不变就会出现如下情况
这个时候就会出现问题
如果我们在方法里面的成员变量前加上this,其他代码均相同,如下图所示
public void setDate(int year,int month,int day)
{
this.year=year;
this.month=month;
this.day=day;
}
大家可以看到,这次的运行结果是和第一次的运行结果是一样的。
首先我们对于问题1进行进行解释:
其他代码均不改变,只改图片中的内容,如果不改也对,因为方法形参名和类的对象成员名是不一样的,但如果加上this一定是对的。
我们可以看到,有三个对象被创造了出来,分别是testdata1,testdata2,testdata3,我们用哪个对象的时候,this就指代的是那个对象,这是编译器自己智能的一个体现
对于问题2:
不加this的时候,变量名和成员变量相同,这个时候编译器就会局部优先原则,就会检测不到外部成员变量,最终局部变量就会给自己进行一个赋值就是0。
4.2什么是this引用
this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作都通过该引用去访问,只不过所有的操作对用户都是透明的,即用户不需要来传递,编译器自动完成。
更深层次的理解就是编译器自动把这个变量隐藏了,原本是在成员方法后面的一个参数应该如下:
public void setDate(TestDate this,int year,int month,int day)
编译器在编译的时候会自动帮你补充TestDate this这个参数。
4.3this引用的特性
1、this的类型:对应类的类型的引用,即哪个对象调用就是哪个对象的引用类型。
2、this只能在成员方法中使用。
3、在成员方法中,this只能引用当前对象,不能引用其他对象。
4、this是成员方法第一个隐藏参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给成员方法,this负责来接受。
5、对象的构造以及初始化
5.1如何初始化对象
如何初始化对象(也就是如何初始化对象当中的成员)
在Java方法内部定义一个局部变量时,必须初始化,否则会编译失效
public static void main(String[] args){
int a;
System.out.println(a);
}
在这部分代码中,因为没有给变量a赋值(初始化),所以在输出a的时候会报错。
如果是对象,需要调用之前的setDate的方法才可以将具体的日期设置到对象中。
通过上述两个例子发现两个问题:
1、每次对象创建好之后调用setDate方法设置具体日期,比较麻烦,那对象该如何初始化呢?
2、局部变量必须要初始化才能使用,为什么成员变量声明之后没有复制依然可以运行呢?
因此Java引进了构造方法
5.2构造方法
5.2.1概念
构造方法,也称为构造器,也是一种特殊的成员方法,名字必须跟类名相同,在创建对象时由编译器自动调用,并且在整个对象的生命周期内只调用一次
class TestDate
{
public int year;
public int month;
public int day;
TestDate(){
} //没有参数的构造方法
TestDate(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) {
TestDate testDate1 = new TestDate();
TestDate testDate2 = new TestDate(2023,6,3);
}
}
在这里,第一行代码调用的就是不带参数的构造方法,第二行代码调用的是带三个参数的构造方法。
注意:在我们没有写构造方法的时候编译器会自动给我们生成一个不带参数的构造方法供我们调用,如果我们写了构造方法,这时编译器就不会帮我们自动生成不带参数的构造方法(这时如果我们要调用不带参数的构造方法时,我们得自己写一个不带参数的构造方法)。(我们编代码的时候经常会因为写了带参数的构造方法,在之后的代码中又调用不带参数的构造方法,这时就会报错)
在没有参数的构造方法当中用this引用直接给对象成员变量(属性)赋值也是可以的
class Student
{
public int age;
public String name;
Student()
{
this.age=10;
this.name="小白";
System.out.println("没有参数的构造方法!");
}
public void print()
{
System.out.println("年龄:"+this.age+" "+"姓名:"+this.name);
}
}
public class Class_And_Object2
{
public static void main(String[] args)
{
Student student=new Student();
student.print();
}
}
那么我们如何在没有参数的构造方法里面调用有参数的构造方法呢?
class Student
{
public int age;
public String name;
Student()
{
this(18,"小白");
System.out.println("没有参数的构造方法!");
}
Student(int age,String name)
{
this.age=age;
this.name=name;
}
public void print()
{
System.out.println("年龄:"+this.age+" "+"姓名:"+this.name);
}
}
public class Class_And_Object2
{
public static void main(String[] args)
{
Student student1=new Student();
student1.print();
Student student2=new Student();
}
}
注意:
1、this()只能在构造方法里面调用构造方法,不能把this()放在一个普通的方法俩面调用构造方法!
2、构造方法当中,不能调用自己。
3、只能放在构造方法内部的第一行
4、不能形成环,比如在第一个构造方法里面调用第二个构造方法,再在第二个构造方法里面调用第一个构造方法。
另外,this除了可以在构造方法里面调用构造方法和this成员变量之外,还可以在方法里面调用另一个方法,这个this可以不用放在第一行
在IDEA中怎么让编译器自己生成构造方法呢?
首先要公开
按住Shift多选
就自动生成成功了
5.2.2特征
1.名字必须与类名相同
2.没有返回值类型,设置为void也不行
3.创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
4.构造方法可以重载
5.如果用户没有显式定义,编译器会自动生成一份默认的构造方法,生成的默认构造方法一定是无参的。一旦用户定义,编译器就不再生成。
6.构造方法中,可以通过this调用其他构造方法来简化代码,注意
(1).this()只能在构造方法里面调用构造方法,不能把this()放在一个普通的方法里面调用构造方法!
(2).构造方法当中,不能调用自己
(3).只能放在构造方法内部的第一行
(4).不能形成环,比如在第一个构造方法里面调用第二个,再在第二个构造方法里面调用第一个。
5.3默认初始化
为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?
class Student
{
public int age;
public String name;
Student()
{
System.out.println("没有参数的构造方法!");
}
Student(int age,String name)
{
this.age=age;
this.name=name;
}
public void print()
{
//this(18,"xiaobai");
System.out.println("年龄:"+this.age+" "+"姓名:"+this.name);
}
}
class Class_And_Object2
{
public static void main(String[] args)
{
Student student1=new Student();
student1.print();
}
}
原因是:成员变量在没有初始化的时候,都有一个默认值
各类数据类型的默认值如下:
5.4就地初始化
class Student{
public int age = 18;
public String name = "小白";
}
在一开始就给成员变量赋值,这种没什么实际上的意义,仅供参考。