05-面向对象基础
✨你好啊,我是“ 罗师傅”,是一名程序猿哦。
🌍主页链接:楚门的世界 - 一个热爱学习和运动的程序猿
☀️博文主更方向为:分享自己的快乐 briup-jp3-ing
❤️一个“不想让我曾没有做好的也成为你的遗憾”的博主。
💪很高兴与你相遇,一起加油!
前言
目标:Java基础编程,熟练Java开发语法和规则,养成良好编程习惯
本节理论较多,注意不要睡着了哈💦💦💦
面向对象
- OOP(object oriented programming), 面向对象编程
- 是一种以对象为中心的编程思想,通过借助对象实现具体的功能
- 将大问题拆分为小问题,然后借助不同对象分别解决,最终实现功能
- POP(procedure oriented Programming),面向过程编程
- 是一种以过程为中心的编程思想,靠自己一步一步去实现功能,需要对每个步骤精确控制
- 强调按步骤实现功能,先分析解决问题锁需步骤,再定义方法实现每个步骤功能,然后依次调用方法,最终实现功能
面向对象语言特征
- 封装(encapsulation)信息隐蔽
- 继承(inheritance)代码重用
- 多态(polymorphism)灵活、接口统一
Java语言、C++、Python等都是面向对象程序设计语言中的一种,所以都具有这三种特征
专业的人去做专业的事情 –> 合适的对象去调用合适的方法
面向对象的特点:
- 更符合人类思想习惯的思想
- 利用对象去实现功能
- 可以将复杂事情简单化(针对要解决问题的用户而言)
- 我们的角色由执行者变成了指挥者
对象理解
自然界中客观存在的事物皆为对象 ,万物皆对象
理解对象
- 任何事物都是一个对象(object)
- 对象由对象组成
- 每个对象都有属性(静态的描述信息)、行为(动态的功能描述)
- 具有相似和行为的对象可以归为一类
类的定义
具有相同属性和行为的对象可以抽象为类(数据类型的一种)
类的组成:
- 属性:指事物的特征,静态描述,例如:手机品牌,价格,尺寸
- 行为:指事物所具有的功能,动态描述;例如:手机可以打电话,也可以发短信
类的理解:
- 类是对现实生活中一类具有共同属性和行为的事物的抽象
- 类是对象的数据类型,类是具有相同属性和行为的一组对象的集合
- 简单理解:类就是对现实事物的一种描述
- 类是引用数据类型中的一种
结论:类是对象的抽象,对象是类的实例
类定义的格式:
1
2
3
4
5
6
7
8
9
10
11
12 [public] class 类名 {
//属性,可以包含多个
[权限修饰符] 数据类型 成员变量名;
//行为,可以包含多个
[权限修饰符] 返回值类型 成员方法名(形参列表) {
具体功能实现
}
//构造器
[权限修饰符] 类名(形参列表) {
初始化语句
}
}类定义步骤:
- 定义类
- 编写类的成员变量
- 编写类的成员方法
对象使用
创建对象格式:
类名 对象名 = new 类名();
调用成员格式:
对象名.成员变量
对象名.成员方法()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 public class Test04_Student {
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu.name); // null
System.out.println(stu.sid); // 0
stu.name = "lwsj";
stu.sid = 1001;
System.out.println(stu.name); // lwsj
System.out.println(stu.sid); // 1001
stu.sleep(100, "躺着");
// 全类名:包名.类名
// com.briup.chap05.pojo.Student@659e0bfd
System.out.println(stu);
}
}类使用总结:
- 一般Java程序会写两个类:基础类,测试类
- 基础类就是我们要实现封装出来的那个类
- 测试类就是包含main方法的类
- 注意:只能在一个类中定义main方法,其是程序的入口,必须唯一
数据类型理解:
Java中对数据类型的描述和定义,都是抽象的,每一种数据类型,都是对一类数据的抽象描述,描述这种数据的基本特点。
int、String和Student都是对数据的抽象描述,不能当做具体的数据使用,如果想使用的这些数据的话,如果想使用的这些数据的话,必须使用int或String类型定义变量,使用Student实例化对象,然后使用变量或对象来参与运算。
类和对象的关系:
类是一组相关属性和行为的集合,它是对某一种具体事物的抽象描述。
也可以吧类看做一个模板,我们使用的对象,就是按照这个模板中的定义,来进行创建的。
- 类是对一类事物的描述,是抽象的
- 对象是一类事物的实例,是具体的
- 类是对象的模板,对象是类的实体
结论:类是一种抽象的数据描述,对象是类的一个具体的实例。
对象内存
1
2
3
4
5
6
7
8 public static void main(String[] args) {
// 实例化对象
Student stu = new Student();
stu.name = "tom";
stu.age = 20;
stu.sayHello();
}
- 单个对象内存图
- 程序运行过程:
- 加载Student类:把Student.class文件内容加载到方法区中
- 加载main方法并运行:整个main方法的代码都被加载到栈区中
- 创建引用类型变量:在栈空间中开辟一块内存空间,用stu标识
- 在堆中开辟内存创建对象,并给属性赋上默认初始值
- 将堆空间对象内存地址值放入stu标识的内存区域中
- 对象属性赋值:将“tom”和20放入堆空间对象内存区域内
- 对象方法调用:找到方法区sayHello方法对应的代码,执行
- main方法继续执行,遇到 } ,程序执行结束
引用类型理解:上述案例中,stu是一个引用类型变量,其对应栈区的一块内存区域,其中放的是一个引用值(地址值),通过这个引用值,系统可以找到对象实际开辟的内存空间(堆区),进而进行对象属性操作或方法调用。
- 多个对象
1
2
3
4
5
6
7
8
9
10
11 >public static void main(String[] args) {
Student s1 = new Student();
s1.name = "lucy";
Student s2 = new Student();
s2.name = "jack";
s2.age = 20;
s1.sayHello();
s2.study(100, "flay");
>}对象内存结论:
- 系统会为每个对象开辟单独的内存空间(堆空间),用来存储对象的属性。
- 类的成员方法存储在方法区,只保留一份,只要是该类的对象,都可以调用。
变量对比
到目前为止,我们学习了两种变量:成员变量、局部变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 public class Test06_Variate {
int num; // 成员变量
public void setNum(int newNum) {
num = newNum; // newNum 局部变量
}
public static void main(String[] args) { // args 局部变量
Scanner sc = new Scanner(System.in); // sc 局部变量
System.out.println("input a num: ");
int number = sc.nextInt(); // 局部变量
Test06_Variate t = new Test06_Variate(); // 局部变量
t.setNum(number);
System.out.println(t.num);
}
}成员、局部变量区别:
- 定义位置不同
- 成员变量:在类中,方法外
- 局部变量:方法内部或方法声明上(形参列表)
- 内存中位置不同
- 成员变量:堆内存
- 局部变量:栈内存(方法内)
- 生命周期不同
- 成员变量:随着对象的存在而存在,随着对象的消失而消失
- 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
- 初始化值不同
- 成员变量:有默认初始值
- 局部变量:没有默认初始值,必须先定义,赋值才能使用
封装特性
概念理解
封装是面向对象三大特征之一,另外两个是继承,多态
封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
其优点如下:
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用方法进行封装,提高了代码的复用性
- 隐藏代码实现细节,提供公共访问方式,简化操作
例子:
我觉得最能体先 封装 的例子就是 适配器模式
比如我们有两种充电器,一个三角三口的,一个是两个直口的。
我们现在只有一个泰国牌子的 插座 ,就是两个孔的。
这个时候我们就可以通过一个转换器 两孔口 —> (一个三口+两个直口的)
这个时候对于两边(用户和提供方)来说都不需要知道转换器具体的内部细节,只需要知道适配器提供了怎么样的接口
封装原则:
- 把不需要对发提供的内容隐藏起来
- 把属性隐藏,提供公共方法对其访问
private
private、public都是权限修饰符,可以用来修饰成员变量、成员方法和构造方法;
- private(私有),用它修饰类的成员(含成员变量、成员方法),则这些成员只能在类内(类的成员函数内部)去使用,其他地方不可以操作;
- public表示公有,用它修饰类的成员(含成员变量、成员方法),则这些成员在类内、类外都可以操作
封装实现
- 使用private修饰成员变量
- 提供对应setXxx()、getXxx()方法,用public修饰
- 具体使用时,借助对象的setXxx方法给属性赋值,getXxx方法获取属性值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package com.briup.chap05.pojo;
/**
* 账户类 封装版
*
* public 所有位置
*
* protected
*
* (不写)
*
* private (最小,只能在类中使用)
*
* @author luozongwei
*
*/
public class Account {
private String id;
private double balance;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
public class Test2_AccountTest {
public static void main(String[] args) {
Account account = new Account();
System.out.println(account.getId());
System.out.println(account.getBalance());
}
}
this关键字
在类中的普通成员方法中,可以使用this关键字,其表示调用当前方法的对象引用,即哪个对象调用该方法,this就代表哪一个对象。
this关键字用法:
- 对成员变量和局部变量进行区分:
this.数据成员
- 调用类中的成员方法:
this.成员方法(实际参数列表)
- 调用类中的其他构造器:this.构造函数(实参)
成员变量与局部变量的区分:
- 方法的形参如果与成员变量同名
- 不带this修饰的变量指的是形参
- 如果要表示成员变量,则必须加this修饰
- 方法的形参与成员变量不同名
- 则不带this修饰的变量指的就是成员变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 private String id;
private double balance;
public void setId(String id) {
this.id = id;
}
public void setBalance(double balance) {
this.balance = balance;
}
// 构造方法
public Account(String id, double balance) {
this.id = id;
this.balance = balance;
}
public Account(String id) {
// 使用this关键字在构造器里调用其他的重载构造器
// 一般是少的调用多的
this(id, 100.0);
}
this内存构成理解
1
2
3
4
5
6 public static void main(String[] args) {
Student stu1 = new Student("zs",21);
stu1.sayHello();
Student stu2 = new Student("tom",19);
stu2.sayHello();
}
- 单个对象内存图
- 多个对象内存图
观察上图可知:每一个对象中,都有自己的this,和其他对象中的互不影响。
当前执行stu1.sayHello()代码的时候,this代表的就是stu1
当前执行stu2.sayHello()代码的时候,this代表的就是stu2
结论:成员方法被哪个对象调用,方法中的this就代表那个对象。即谁调用,this就代表谁。
构造方法
构造方法可以对对象进行初始化操作,即为对象开辟内存空间的时候,给对象的成员成员赋初值。
构造方法格式:
1
2
3 [修饰符] 类名(参数列表) {
初始化语句s;
}注意事项:
- 构造方法一般使用public修饰
- 构造方法没有返回值类型,连void都没有
- 构造方法名和类名相同(区分大小写)
- 构造方法可以重载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package com.briup.chap05.pojo;
public class Teacher {
private String name;
private double salary;
// 无参构造
public Teacher() {
System.out.println("Teacher()...");
}
public Teacher(String name, double salary) {
System.out.println("Teacher(String, double)...");
this.name = name;
this.salary = salary;
}
public void show() {
System.out.println("name: " + name);
System.out.println("salary:" + salary);
}
}执行时机:
- 创建对象的时候调用,每创建一次对象,就会执行一次构造方法
- 不能手动调用构造方法
1
2
3
4
5
6
7
8
9 public static void main(String[] args) {
Teacher t1 = new Teacher();
t1.show();
System.out.println("--------------------------");
Teacher t2 = new Teacher("kevin", 13099.5);
t2.show();
// 手动调用构造方法,错误用法,无法通过编译
// t2.Teacher();
}创建对象时构造器会被自动调用(实例化对象时指定的那 个构造方法),其完成了对象属性的初始化。
注意事项补充:
- 用户不定义构造方法,系统会提供一个无参构造方法
1
2
3 public 类名(){
// nothing to do
}
- 用户定义构造方法,系统则不再提供无参构造方法
- 用户不需要也不可以主动调用构造方法,系统会自动调用
对象创建步骤:
1
2
3 public static void main(String[] args) {
Student stu = new Student("zhang", 23);
}
- 将Student.class文件加载到内存方法区
- 在main栈帧开辟一块内存,用stu标识
- 在堆中开辟内存创建对象
- 给属性以默认初始值(null,0)
- 属性进行显式初始化(如果存在的话,比如private int age = 10;)
- 调用构造方法,用(“zhang”, 23)给属性赋值
- 将堆中对象的内存地址赋值给stu,对象创建完成
this补充
this特殊用法:
在构造方法中,可以借助this关键字调用其他构造方法
具体格式为: this(实际参数列表);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 public class Teacher {
//...省略
//该类已经成功定义2参构造器,定义过程省略
//public Teacher(String name, double salary);
//this特殊用法:在构造方法中,调用其他构造方法
public Teacher(String name) {
//必须是构造方法的第一行有效代码
this(name,0);
}
}
public class Test10_This {
public static void main(String[] args) {
//调用Teacher(String)构造方法实例化对象
//底层借助Teacher(String, double)实现
Teacher t = new Teacher("larry");
t.show(); //
}
}
// Teacher(String, double)...
// name: lucy
// salary:0.0构造方法Teacher(String)底层借助Teacher(String, double)实现了 功能。
注意: this(实际参数列表) 必须是构造方法中的第一行有效代码。
❤️❤️❤️忙碌的敲代码也不要忘了浪漫鸭!
盛年不再来,一日难再晨,及时当勉励,岁月不待人。—- 陶渊明💪