Day07
面向对象
1、快速开始
编写案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-demax6wl-1668818821518)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118095633155.png)]
面向过程的写法:
public class Test {
public static void main(String[] args) {
printTotalScore("波妞",100,100);
printAverageScore("波妞",100,100);
printTotalScore("波仔",59,99);
printAverageScore("波仔",59,99);
}
public static void printTotalScore(String name, double chinese, double math) {
System.out.println(name + "同学的各科总分是:" + (chinese + math));
}
public static void printAverageScore(String name, double chinese, double math) {
System.out.println(name + "同学的各科平均分是:" + (chinese + math) / 2.0);
}
}
面向对象的写法:
package com.itheima.quickstart;
import com.itheima.quickstart.Student;
public class Demo01 {
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "波妞";
s1.yuwen = 100;
s1.math = 100;
s1.printTotalScore();
s1.printAverageScore();
System.out.println("========");
Student s2 = new Student();
s2.name = "波仔";
s2.yuwen = 59;
s2.math = 99;
s2.printTotalScore();
s2.printAverageScore();
}
}
package com.itheima.quickstart;
import com.itheima.quickstart.Student;
public class Demo01 {
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "波妞";
s1.yuwen = 100;
s1.math = 100;
s1.printTotalScore();
s1.printAverageScore();
System.out.println("========");
Student s2 = new Student();
s2.name = "波仔";
s2.yuwen = 59;
s2.math = 99;
s2.printTotalScore();
s2.printAverageScore();
}
}
2、深刻认识面向对象
面向过程:开发一个个的方法,有数据要处理了,就把数据交给方法
面向对象:开发一个个的对象,有数据要处理了,就把数据交给对象,再调用对象的方法来完成对数据的处理
1.面向对象的好处
- 万物皆对象
- 符合人类的习惯,编程会更简单,更直观
2.程序中的对象
-
对象本质是一种特殊的数据结构,可以把对象看成一张纸具体的表;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-52cq7AFr-1668818821519)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118103240211.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PKnlJ6aX-1668818821519)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118103345803.png)]
3.对象是怎么出来的
-
对象是类new出来的,必须要有类才能创建对象
-
class也就是类,也称为对象的设计图(或者是对象的模板)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F2PIgHuy-1668818821520)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118105004874.png)]
-
对象就相当于向模板里放具体的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b2MsLpmd-1668818821520)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118105155965.png)]
4.怎么设计类
-
类:成员变量,成员方法,构造器,代码块,内部类
-
现在阶段设计类:成员变量,成员方法
- 成员变量:代表类的属性
- 成员方法:代表类的行为
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h9LUXDaw-1668818821520)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118105514028.png)]
-
怎么得到类的对象
类名 对象名 = new 类名 Student s1 = new Student
-
怎么使用对象
-
访问属性
对象名.成员变量
-
访问行为
对象名.方法名()
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z0l0uH5R-1668818821521)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118110150703.png)]
Car类:
package com.itheima.quickstart;
public class Car {
String carName;
double price;
public void start(){
System.out.println(carName+"启动");
}
public void run(){
System.out.println(carName+"跑");
}
public void sell(){
System.out.println(carName+"卖的价格为:"+price+"万");
}
}
测试类:
package com.itheima.quickstart;
public class Car {
String carName;
double price;
public void start(){
System.out.println(carName+"启动");
}
public void run(){
System.out.println(carName+"跑");
}
public void sell(){
System.out.println(carName+"卖的价格为:"+price+"万");
}
}
3.对象在计算机中的执行原理
对象在计算机中的执行原理
- 测试类的字节码文件,main进入方法区
- 创建一个实体类对象,创建出来的对象在堆内存开辟区域,并且有自己的地址值,对象包含对象的属性(开始都是默认值),成员方法(存储的是实体类在方法区的地址值,这样节省内存)
- 对象变量,存储在栈内存,对象变量存储对象在堆内存的地址值
- 对象变量根据地址值去堆内存找到实体类的属性进行赋值,堆内存中的属性被修改
- 对象变量调用实体类方法,根据地址值去堆内存找到实体类的地址值,然后到方法区找到对应方法调用,调用的方法进入栈内存运行,运行完后出栈
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xCMDoR5h-1668818821522)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118162959632.png)]
怎么识别引用变量
- 变量内部存储的是对象的地址值,而不是具体的数据
某个对象没有任何变量指向它,需注意
- 当堆内存中的对象,没有被任何变量引用(指向)时,就会被判断为内存中的"垃圾"
- Java存在自动垃圾回收机制,会自动清除掉垃圾对象
多个变量指向同一个对象
-
多个变量指向同一个对象,这些变量中存储的是同意对象的地址值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4rlkzT6n-1668818821523)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118164519774.png)]
4、类和对象的一些注意事项
-
类名建议用英文单词,首字母大写,满足驼峰模式,且要有意义,比如:Student、Car…
-
类中定义的变量也称为成员变量(对象的属性),类中定义的方法也称为成员方法(对象的行为)。
-
成员变量本身存在默认值,同学们在定义成员变量时一般来说不需要赋初始值(没有意义)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ohn60Csc-1668818821524)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118163905632.png)] -
一个代码文件中,可以写多个class类,但只能一个用public修饰,且public修饰的类名必须成为代码文件名。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-US5xu90t-1668818821526)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118164302656.png)]
-
对象与对象之间的数据不会相互影响,但多个变量指向同一个对象时就会相互影响了。
-
如果某个对象没有一个变量引用它,则该对象无法被操作了,该对象会成为所谓的垃圾对象。
5、this关键字
1.this的定义
- this就是一个变量,可以用在方法中,来拿到当前对象,哪个对象调用方法
实体类;
package com.itheima.thisdemo;
public class Student {
String name;
double score;
//this就是一个变量;用来指向当前对象的地址
//用于解决变量名称冲突的问题
//当方法中有this,就相当于在方法的形参中有 (当前对象类型 对象名) 这样一个形参,只是默认不写
public void print(double score) {
if (this.score >= score) {
System.out.println("恭喜,考上");
} else {
System.out.println("很遗憾");
}
}
}
测试类:
package com.itheima.thisdemo;
public class Student {
String name;
double score;
//this就是一个变量;用来指向当前对象的地址
//用于解决变量名称冲突的问题
//当方法中有this,就相当于在方法的形参中有 (当前对象类型 对象名) 这样一个形参,只是默认不写
public void print(double score) {
if (this.score >= score) {
System.out.println("恭喜,考上");
} else {
System.out.println("很遗憾");
}
}
}
2.this的执行原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W0jdIOPv-1668818821527)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118221425294.png)]
3.this的应用场景
- this主要用来解决对象的成员变量与方法内部变量的名称一样时,导致访问冲突问题的
package com.itheima.thisdemo;
public class Student {
String name;
double score;
//this就是一个变量;用来指向当前对象的地址
//用于解决变量名称冲突的问题
//当方法中有this,就相当于在方法的形参中有 (当前对象类型 对象名) 这样一个形参,只是默认不写
//形参score与成员变量score命名冲突
public void print(double score与成员变量score命名冲突) {
if (this.score >= score) {
System.out.println("恭喜,考上");
} else {
System.out.println("很遗憾");
}
}
}
4.方法里的this怎么拿到它的调用对象的
- 当去调用方法的时候,this会为参数神不知鬼不觉的传入方法中,每个对象都有一个this,this不是你设置的属性,而是Java给每个类都设置的标记,你察觉不到它的存在,但它一直都在,方法的形参部分相当于有this这个形参,当调用printThis方法时,会传入this,也就是当前调用方法的对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VnD9tVPu-1668818821527)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118221927962.png)]
6、构造器
1.构造器的定义
-
修饰符 类名(形参列表){ ... }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qSRk7gCA-1668818821528)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118224956997.png)]
2.构造器的作用
- 构造器也叫构造方法,是一种特殊的方法,定义在类中,用来初始化一个类的对象,并返回对象的地址
3.调用构造器得到对象的格式
类 变量名 = new 构造器;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAQwk5Ix-1668818821529)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118225233628.png)]
4.构造器的分类
- 无参构造器(默认存在),初始化对象时,成员变量的数据采用默认值;
- 有参构造器(需明确定义,但有有参构造器后,就默认没有无参,需要无参构造器也许明确定义),初始化对象时,同时可以接收参数为对象的成员变量进行赋值
5.构造器的注意事项’
- 构造器的名字必须和类名是一致的
- 定义构造器的时候一定不能写返回值类型,void也不行
- 任何类定义出来,默认就有无参构造器,写不写都行
- 一旦定义了有参构造器,那么无参构造器就没有了。如果还想要用无参构造器,此时需要手写一个无参构造器
实体类:
package com.itheima.constructor;
public class Student {
String name;
int age;
public Student(){
System.out.println("无参构造器");
}
public Student(String name,int age){
this.name = name;
this.age = age;
System.out.println("有参构造器");
}
}
测试类:
package com.itheima.constructor;
public class Demo {
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(s1.name);
System.out.println(s1.age);
System.out.println(s1);
Student s2 = new Student("西安",10000);
System.out.println(s2.name);
System.out.println(s2.age);
System.out.println(s2);
}
}
7、封装(encapsulation)
面向对象的三大特征:封装,继承,多态
1.封装的定义
-
它指的是将对象的属性信息隐藏在对象内部,不允许外部程序直接访问对象内部属性信息,而是通过该类所提供的方法来实现对内部属性信息的操作和修改
封装后:
//实体类 package com.itheima.encapsulation; public class Student { private String name; private int age; public int getAge() { return age; } public void setAge(int age) { if (age < 0 || age > 150) { System.out.println("输入错误"); } this.age = age; } } //测试类 package com.itheima.quickstart; public class Student { String name; double yuwen; double math; public void printTotalScore(){ System.out.println(name + "总成绩为:"+(yuwen+math)); } public void printAverageScore(){ System.out.println(name + "平均分为:"+(yuwen+math)/2); } }
没封装
//实体类
package com.itheima.quickstart;
public class Student {
String name;
double yuwen;
double math;
public void printTotalScore(){
System.out.println(name + "总成绩为:"+(yuwen+math));
}
public void printAverageScore(){
System.out.println(name + "平均分为:"+(yuwen+math)/2);
}
}
//测试类
package com.itheima.quickstart;
import com.itheima.quickstart.Student;
public class Demo01 {
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "波妞";
s1.yuwen = 100;
s1.math = 100;
s1.printTotalScore();
s1.printAverageScore();
System.out.println("========");
Student s2 = new Student();
s2.name = "波仔";
s2.yuwen = 59;
s2.math = 99;
s2.printTotalScore();
s2.printAverageScore();
}
}
2.封装设计规范
- 合理隐藏,合理暴露
- 如何合理隐藏,合理暴露
- 合理隐藏:一般建议对成员变量使用private关键字进行修饰(private修饰的成员变量只能在本垒中访问)
- 合理暴露:必要的时候为成员变量提供public修饰的getter,setter方法,让对象取值和赋值
- 成员方法根据是否需要被当前类外面的类访问去决定使用private还是public
8、实体JavaBean
1.实体类
- 就是一种特殊形式的类,其对象可以用于在程序中封装数据
2.实体JavaBean需满足的书写格式
- 这个类的成员变量都要私有,提供相应的getter,setter方法
- 类中提供一个公共的无参构造器和有参构造器
9、面向对象的综合案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t3ET1CcF-1668818821530)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221118232416266.png)]
-
实体类
package com.itheima.Demo; public class Movie { private int id; private String name; private double price; private double score; private String director; // 导演 private String actor; // 主演 private String info; //其他 public Movie() { } public Movie(int id, String name, double price, double score, String director, String actor, String info) { this.id = id; this.name = name; this.price = price; this.score = score; this.director = director; this.actor = actor; this.info = info; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } public String getDirector() { return director; } public void setDirector(String director) { this.director = director; } public String getActor() { return actor; } public void setActor(String actor) { this.actor = actor; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } }
-
测试类
package com.itheima.Demo; import java.util.Scanner; public class Test { public static void main(String[] args) { //1, "《扫黑行动》", 38.9, 9.7, "林德禄", "周一国", "12万人想看" // 2, "《万里归途》", 59.9, 9.6, "饶晓志", "张译", "13.5万人想看" // 3, "《哥,你好》", 35.8, 9.5, "张栾", "马丽", "17.9万人想看" // 4, "《名侦探柯南》", 69.5, 9.1, "满仲劝", "高山南", "17.9万人想看" //需求1:打印全部电影的信息 //需求2:根据id,查询电影全部信息 //需求3:做一个电影信息系统 //需求1:1.创建对象,录入数据 Movie m1 = new Movie(1, "《扫黑行动》", 38.9, 9.7, "林德禄", "周一国", "12万人想看"); Movie m2 = new Movie(2, "《万里归途》", 59.9, 9.6, "饶晓志", "张译", "13.5万人想看"); Movie m3 = new Movie(3, "《哥,你好》", 35.8, 9.5, "张栾", "马丽", "17.9万人想看"); Movie m4 = new Movie(4, "《名侦探柯南》", 69.5, 9.1, "满仲劝", "高山南", "17.9万人想看"); //需求1:2.将创建好的对象,放入一个数组中,数组类型与对象类型相同 Movie[] movies = {m1, m2, m3, m4}; // showAllMovies(movies); // getMovieById(movies,3); movieSystem(movies); } //需求3:做一个电影信息系统 public static void movieSystem(Movie[] movies) { Scanner sc = new Scanner(System.in); while (true) { System.out.println("======电影信息系统======"); System.out.println("请输入下列编号"); System.out.println("1、查询全部电影信息"); System.out.println("2、根据电影id查询电影详情"); System.out.println("3、退出系统"); int command = sc.nextInt(); //因为拿到的是值,且情况有三种,直接值匹配,switch switch (command) { case 1: showAllMovies(movies); break; case 2: System.out.println("请输入查询的id"); int id = sc.nextInt(); getMovieById(movies, id); break; case 3: System.out.println("退出成功"); //退出系统就是直接结束我们的方法 return; default: System.out.println("输入有误,重新输入"); } } } //需求1:3.编写打印全部电影方法 //不需要返回值直接打印即可,需要形参得有数据让我们打印 public static void showAllMovies(Movie[] movies) { //遍历 for (int i = 0; i < movies.length; i++) { Movie movie = movies[i];//遍历拿到一部打印 //因为数组中是对象变量,所以直接打印是地址值,我们需要用get,set System.out.println("电影名称:" + movie.getName()); System.out.println("评分:" + movie.getScore()); System.out.println("======================"); } } //需求2:1.编写方法,不需要返回值,需要传递值,数组,id public static void getMovieById(Movie[] movies, int id) { //2.遍历判断 for (int i = 0; i < movies.length; i++) { Movie movie = movies[i]; if (movie.getId() == id) { System.out.println("电影名" + movie.getName()); System.out.println("票价" + movie.getPrice()); System.out.println("评分" + movie.getScore()); System.out.println("导演" + movie.getDirector()); System.out.println("演员" + movie.getActor()); System.out.println("其他" + movie.getInfo()); return;//匹配到以后直接结束整个方法 } } //3.全部遍历完若没有找到 System.out.println("输入有误"); } }
10、成员变量和局部变量的区别
区别 | 成员变量 | 局部变量 |
---|---|---|
类中位置不同 | 类中,方法外 | 常见于方法内 |
初始化值不同 | 有默认初始化值,无需初始化 | 没有默认初始化值,使用前要赋值 |
内存位置不同 | 堆内存 | 栈内存 |
生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的消失而消失 |
作用域 | 整个对象 | 所归属的大括号中 |
}
//3.全部遍历完若没有找到
System.out.println(“输入有误”);
}
}
### 10、成员变量和局部变量的区别
| 区别 | 成员变量 | 局部变量 |
| :----------: | :----------------------------------------: | :----------------------------------------: |
| 类中位置不同 | 类中,方法外 | 常见于方法内 |
| 初始化值不同 | 有默认初始化值,无需初始化 | 没有默认初始化值,使用前要赋值 |
| 内存位置不同 | 堆内存 | 栈内存 |
| 生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的消失而消失 |
| 作用域 | 整个对象 | 所归属的大括号中 |