初识面向对象
类与对象
什么是对象?
在编程语言和现实世界中,对象是一个非常重要的概念。所谓“万物皆对象”,指的是现实存在的客观事物都是对象。
什么是面向对象?
①假如我们有一天去动物园看动物
②我们对管理员描述想看的动物需求。
- 胖的
- 可爱的
③管理员听后,带我们去看了熊猫班卜和黑熊吨吨
我们去动物园看动物的这个过程,实际上就是一个面向对象的过程。
我们去动物园看动物的时候,当说出我们需求的时候,此时的动物是虚拟的;当管理员带领我们去看动物的时候,此时的动物才是实体,这是我们生活中处理问题的方式。
类与对象的关系
- 类是模型(模板),确定对象将会拥有的特征(属性)和行为(方法)
- 对象是类的实例表现
- 类是对象的类型
- 对象是特定类型的数据
属性和方法
属性:对象具有的各种静态特征——“对象有什么”
方法:对象具有的各种动态行为——“对象能做什么”
回到我们逛动物园的实例,动物具有的特征就是对象的属性;动物可以做的事情就是对象的方法
总结
- 类
- 抽象的概念
- 模板
- 对象
- 一个实际存在的具体事物
创建类
面向对象在java编程中的实现步骤:
创建一个宠物猫类Cat.java,描述该宠物猫的属性和行为方法
package animal;
/**
* 宠物猫类
* @author Zhao
*
*/
public class Cat {
//成员属性:名称、年龄、体重、品种
String name;//名称
int month;//年龄
double weight;//体重
String species;//品种
//方法:跑、吃东西
//跑动的方法
public void run() {
System.out.println("小猫快跑!");
}
//吃东西的方法
public void eat() {
System.out.println("小猫吃东西!");
}
}
实例化对象
创建一个测试类CatTest.java,去实例化对象,并调用对象的属性和方法。
package object.start;
/**
* @author Ning
* @date 2021/9/20 10:57
*/
public class CatTest {
public static void main(String[] args) {
//实例化对象 ——>通过new关键字
Cat one = new Cat();
//调用对象的属性
one.name = "花花";
one.month = 2;
one.weight = 1000;
one.species = "英国短毛猫";
//调用对象的方法
one.eat();
one.run();
//输出对象的属性值
System.out.println("名字:"+one.name);
System.out.println("年龄:"+one.month);
System.out.println("体重:"+one.weight);
System.out.println("品种:"+one.species);
}
}
注意:对象的属性如果没有进行初始化,系统会默认地给对象的属性赋初始值。
整型的初始值为0
浮点型的初始值为0.0
字符串的初始值为null
单一职责原则
我们会发现之前写的代码都是放在一个类里面,包括主方法;而在面向对象的编程中,主方法和封装属性、方法的类是拆开的,这就是 单一职责原则(单一功能原则)
单一职责原则
所谓“单一职责原则”表示的是一个类中有且只有一个引起变化的原因。
简单地来说就是一个类最好只有一个功能。
比如说下面正在做实验的仓鼠:
假如我们想观察仓鼠的运动,那就只需要让它做跑动这一件事就可以了;如果既想让它跑,同时还让它跑一段距离再跳起来,那么这只仓鼠的内心是崩溃的。
因此,在一个类中,如果该类承担的功能越多,那么此类的 交融与耦合度就会越高,被复用的可能性就会越低。
交融、耦合性越高会发生什么?
交融、耦合性越高可能会引发同类中其他职责的变化,进而影响整个程序的运行。
这就好比我们生活中过马路的情景,很多人喜欢边走路边玩手机;也有很多人喜欢边开车边打电话,因此一旦发生事故就是一件非常可怕的事情。
new关键字
在面向对象中,我们通过new关键字去实例化对象。
实例化对象
实例化对象的过程可以分成两个部分:
①声明对象 Cat one
②实例化对象 new Cat();
声明对象的时候,此时内存空间中的one是null,那么它是无法去访问属性和方法的。
为什么实例化对象后就可以访问属性和方法了?
当实例化对象后,会在内存的堆空间中去开辟一块空间,从而完成对象信息的初始化操作。
注意:声明对象和实例化对象在不同的空间中
声明对象在栈空间中;实例化对象在堆空间中。
那么栈空间和堆空间是怎么关联起来的?
实例化对象后,会将对象在堆空间中的内存地址存放到栈中,从而使声明的对象指向实例化的空间。
如果使用new关键字实例化一个对象,两个对象会发送冲突吗?
我们修改一下CatTest.java的代码,我们再new一个对象
package object.start;
/**
* @author Ning
* @date 2021/9/20 10:57
*/
public class CatTest {
public static void main(String[] args) {
//实例化对象 ——>通过new关键字
Cat one = new Cat();
//再实例化一个对象
Cat two = new Cat();
//调用对象的属性
one.name = "花花";
one.month = 2;
one.weight = 1000;
one.species = "英国短毛猫";
//给two的属性赋值
two.name = "凡凡";
two.month = 1;
two.weight = 800;
two.species = "中华田园猫";
//输出对象的属性值
System.out.println("名字:"+one.name);
System.out.println("年龄:"+one.month);
System.out.println("体重:"+one.weight);
System.out.println("品种:"+one.species);
System.out.println("------------------------------");
System.out.println("名字:"+two.name);
System.out.println("年龄:"+two.month);
System.out.println("体重:"+two.weight);
System.out.println("品种:"+two.species);
}
}
运行结果:
名字:花花
年龄:2
体重:1000.0
品种:英国短毛猫
名字:凡凡
年龄:1
体重:800.0
品种:中华田园猫
我们发现使用new关键字实例化的两个对象是不会发生冲突的。
每当我们使用new关键字时,都会在堆空间中开辟一块空间来存储对象的地址,虽然都是猫类,但是所指向的地址不同,就算二者的属性值完全相同,二者之间是互不影响的。
这就好比我们有两套房子,就算房子的外观内饰一模一样,房子的钥匙也是两套不同的钥匙。
对象实例化是不是只有new这一种实现方式呢?
我们修改一下CatTest.java代码
package object.start;
/**
* @author Ning
* @date 2021/9/20 10:57
*/
public class CatTest {
public static void main(String[] args) {
//实例化对象 ——>通过new关键字
Cat one = new Cat();
//将对象one赋值给对象two
Cat two = one;
//调用对象的属性
one.name = "花花";
one.month = 2;
one.weight = 1000;
one.species = "英国短毛猫";
//给two的属性赋值
two.name = "凡凡";
two.month = 1;
two.weight = 800;
two.species = "中华田园猫";
//输出对象的属性值
System.out.println("名字:"+one.name);
System.out.println("年龄:"+one.month);
System.out.println("体重:"+one.weight);
System.out.println("品种:"+one.species);
System.out.println("------------------------------");
System.out.println("名字:"+two.name);
System.out.println("年龄:"+two.month);
System.out.println("体重:"+two.weight);
System.out.println("品种:"+two.species);
}
}
运行结果:
名字:凡凡
年龄:1
体重:800.0
品种:中华田园猫
名字:凡凡
年龄:1
体重:800.0
品种:中华田园猫
我们发现对象的属性值都成为了对象two设置的属性值。
这实际上是对象one将内存地址复制了一份,放入到了对象two里面,此时,二者都指向了同一块内存区域,因此二者无论是谁对属性进行修改,都会影响另一方。
这就好比是一个房子里面住进了两个人,任何一个人都可以对房子进行装修。
构造方法
构造方法也称“构造器”、“构造函数”。可以通过构造方法来完成对象初始化的相关设置。
构造方法的语法
访问修饰符 构造方法名(参数列表){
初始化代码块
}
构造方法的相关规则
① 构造方法与类名必须相同且无返回值
② 只能在对象实例化的时候使用
③ 当没有指定构造方法时,系统会默认提供无参构造方法
④ 当有指定构造方法,无论是有参、无参构造方法,都不会自动添加无参构造方法
⑤ 一个类中可以有多个构造方法
无参构造方法
我们在写Cat.java文件中的代码时,没有写无参构造方法,系统会给我们自动地添加一个无参构造方法,那这次我们手动在Cat.java中添加无参构造方法
//无参构造方法
public Cat(){
System.out.println("Cat的无参构造方法,这是我们手动添加的。。。");
}
在CatTest.java中去调用我们手动添加的无参构造方法
package object.start;
/**
* @author Ning
* @date 2021/9/20 10:57
*/
public class CatTest {
public static void main(String[] args) {
//实例化对象 ——>通过new关键字
Cat one = new Cat(); //系统通过无参构造方法初始化对象
}
}
运行结果:
Cat的无参构造方法,这是我们手动添加的。。。
有参构造方法
我们之前给对象的属性赋初始值的时候是通过 对象名.属性名=属性值; 去完成赋值。当对象的属性过多时,一个个赋值会比较麻烦,因此我们可以在类中添加有参构造方法对属性的值进行初始化操作。
在Cat.java中添加有参构造方法
//有参构造方法
public Cat(String name, int month, double weight, String species) {
name = name;
month = month;
weight = weight;
species = species;
}
在CatTest.java中进行测试
package object.start;
/**
* @author Ning
* @date 2021/9/20 10:57
*/
public class CatTest {
public static void main(String[] args) {
//实例化对象 ——>通过new关键字
//使用有参构造方法对属性进行初始化
Cat one = new Cat("花花",2,1000,"英国短毛猫");
System.out.println("名字:"+one.name);
System.out.println("年龄:"+one.month);
System.out.println("体重:"+one.weight);
System.out.println("品种:"+one.species);
}
}
运行结果:
名字:null
年龄:0
体重:0.0
品种:null
拓展
我们明明通过有参构造方法对属性值进行初始化,但是为什么没有赋值成功?
我们犯了一个逻辑错误,我们的有参构造方法中出现了一条警告信息——The assignment to variable name has no effect. 该变量未起作用。
原因是因为当参数列表中的参数名称与成员变量名称同名时,由于没有具体指定,变量到底是构造方法中的变量还是成员变量,系统会采用就近原则,因此不会给成员变量赋值。
解决方法有两种:
① 修改参数列表中的变量名 Cat.java
//有参构造方法
public Cat(String newName, int newMonth, double newWeight, String newSpecies) {
name = newName;
month = newMonth;
weight = newWeight;
species = newSpecies;
}
CatTest.java运行后的结果:
名字:花花
年龄:2
体重:1000.0
品种:英国短毛猫
② 通过this关键字
this关键字
this可以指代当前对象,所谓当前对象就是谁调用this就指向谁。this关键字即可以访问属性也可以访问方法。
通过this关键字修改Cat.java的有参构造方法
//有参构造方法
public Cat(String name, int month, double weight, String species) {
this.name = name;
this.month = month;
this.weight = weight;
this.species = species;
}
CatTest.java运行结果:
名字:花花
年龄:2
体重:1000.0
品种:英国短毛猫