目录
一、面向对象概述
面向对象术语:
OOA 面向对象分析
OOD 面向对象设计
OOP 面向对象编程
完成一个软件的过程:分析、设计、编程。
PM 指项目经理
什么是面向对象?
面向对象就是写程序的套路。
面向可以理解为找、拿;对象可以理解为东西;面向对象编程:找\拿 东西过来编程。
为什么用面向编程?
面向对象编程与日常生活中解决问题的方法相一致,例如扫地,必须先找一个扫把或者去某个地方,就必须找辆车,因此写程序解决问题同样需要找一个"东西"来帮助我们实现,这样写程序更符合人类的思维习惯,使编程更简单、更好理解。
面向对象学什么?
通过面向对象的语法学会自己设计对象并使用。例如生活中要拧一颗螺丝就要设计一个螺丝刀来解决问题。
二、设计对象并使用
1、类是什么?
例如日常生活中造房子就需要设计图,通过设计图来建造,而这个设计图就相当于是类。
是对象共同特征的描述。
对象:是真实存在的具体实例。 所以对象就是实例,实例就是对象。
因此,在java中必须先设计类,才能创建对象并使用。
2、如何创建类?
2、创建类注意事项
- 类名首字母建议大写,满足驼峰模式,不能使用关键字,必须是合法的标识符
- 一个java文件中可以定义多个class类,但只能一个类是public修饰,而且public修饰的类名必须成为代码文件名,建议一个代码文件只定义一个类。
- 成员变量(属性)的完整定义格式:修饰符 数据类型 变量名称 = 初始化值;一般无需指定初始化值,存在默认值。
修饰符 数据类型 变量名称 = 初始化值
public int a = 0;
/*
初始化 默认值规则
byte short int long 0
double float 0.0
boolean false
String等引用类型 null
*/
三、对象在内存中的运行机制
1、多个对象的内存图
先将.class文件加载到方法区,然后将main方法提到栈内存中执行,执行第一句,将Car类的.class文件加载到方法区,(等号左边)定义了一个引用类型的变量c1作为对象名,是一个局部变量,因此,在栈内存中的main方法内分配一块区域存储Car 类型变量 c1,接着执行等号右边,在堆内存中开辟一块内存空间,代表一个Car对象,在对象中开辟区域存放他相应的属性信息,并给他们附默认值,由于对象的方法可能会很多,会极大占据堆内存空间,因此在堆内存中只会存放这些方法的地址(引用地址),通过这个地址去引用方法区的方法,这样堆内存中的对象就表示出来了。对象实际就是一块内存空间
接着将这块内存空间的地址赋值给左边的c1变量,由c1变量指向这个对象,因此c1中存放的就是对象在堆内存中的地址,然后执行第二行代码,通过c1变量中的地址,找到这个对象,再将这个对象中的name成员变量改成 "奔驰" ,price成员变量改为 39.78,访问c1变量指向对象中的name和price,再执行输出语句,紧接着通过c1调用start()方法,调用方法的原理就是通过c1中存储的地址找到这个对象,然后通过对象中的方法引用的地址找到start()方法,并将start()方法提取到栈内存中执行,由于这个start()方法知道是c1调用的,因此它自然会访问c1中的name信息和price信息,执行start()方法,打印 "奔驰启动了",run()方法同理
在创建一个新的对象名为c2,在栈内存中的main方法内分配一块区域,在堆内存中开辟一块区域代表一个对象,并在该区域内开辟空间存放其属性信息,再将这个对象的地址赋给c2,通过c2中的地址找到这个对象,将这个对象中的name修改为 "宝马" ,price修改为 "38.98",执行输出语句,再通过c2指向对象中的方法引用找到start()方法的地址,执行这个方法。
2、两个变量指向同一个对象内存图
先将.class文件提到方法区,再将main方法加载到栈内存,开始执行第一行代码,将Student类的.class文件提到方法区,在栈内存中的main方法内开辟一块区域存储Student引用类型变量s1,并在堆内存中的main方法内分配一块区域代表一个Student对象,在对象中开辟区域存放其相应的属性信息,将对象在堆内存中的地址赋给s1存储,通过s1中存储的地址,找到其对应的对象,修改他的属性信息,最后通过对象中的方法引用找到study()方法并调用,(重点)再在栈内存中开辟一块区域存放变量s2,将s1中存储的地址赋给s2,使s2也指向堆内存中的对象,再通过s2变量修改其属性值。
补充:垃圾回收
当堆内存中的对象,没有被任何变量引用(指向)时,就会判定为内存中的"垃圾",在java中有自动垃圾回收器,会定期进行清理。
java虚拟机提供了一个系统级的垃圾回收器线程,它负责自动回收那些无用对象占用的内存,这种内存回收的过程称为垃圾回收。
四、模拟购物车
见案例补充购物车的实现。
五、构造器
1、学习构造器的目的
- 真正知道对象具体是通过调用什么代码得到的
- 能够掌握为对象赋值的其他简便写法
- 为以后学习面向对象编程的其他内容做支撑
2、构造器的基本知识
new出来的东西就相当于一个构造器
3、构造器的注意事项
- 任何类定义出来,默认就自带了无参数构造器,写不写都有。Car c = new Car()
- 一旦定义了有参数构造器,那么无参数构造器就没有了,如果还想用无参数构造器,此时就需要自己手写一个无参数构造器
六、this关键字
1、this关键字是什么
- this代表当前对象的地址
- 具体用在在构造器、方法中
//无参构造器
public Car() {
//this输出了对象的地址
System.out.println("无参数构造器" + this);
}
这个this会输出当前对象的地址。
2、this关键字的作用
可以用于指定访问当前对象的成员变量、成员方法。
- 当this出现在有参数构造器
public class Car {
String name;
double price;
//有参数构造器
//设置参数 n,p在实际开发中会被嫌弃,必须明确传入参数的名称
public Car(String n , double p) {
System.out.println("有参数构造器被调用");
name = n;
price = p;
}
}
因此改进的有参数构造器为:
public class Car {
String name;
double price;
//有参数构造器
//传入参数见名知义
public Car(String name , double price) {
System.out.println("有参数构造器被调用");
//而如果这样进行传参并不能为当前对象的 name和price进行赋值
//因为形参接受到传入的数据会就近传入给局部的形参name,不会赋给当前对象的name
//name = name;
//price = price;
//所以要通过this获取当前对象的属性进行赋值
this.name = name;
this.price = price;
}
}
- 当this出现在成员方法中的用法
区分当前对象的属性和当前的传入参数。
七、封装
1、封装的基本思想
面向对象的三大特性:封装、继承、多态
封装的基本思想:决定属性和行为归属谁的问题。
封装的作用: 告诉我们,如何正确设计对象的属性和方法。
封装的原则:对象代表什么,就得封装对应的数据,并提供数据对应的行为。
封装思想举例:
1、人画圆
定义一个人对象、一个圆对象和一个画圆方法,画圆这个方法就要封装在圆对象中,因为人画圆,这个圆是圆对象自己画的,人只是调用圆对象中的画圆方法。
2、人关门
定义一个门对象、人对象和一个关门方法,关门方法就要封装在门对象中,门是自己关的,因为人只是调用了门对象中封装的关门方法使门自己关上。
2、如何更好的封装
public class Student {
//类私有属性 age 对外不能直接访问它
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
//设置年龄条件 0 - 200 岁
if (age >= 0 && age <= 200) {
this.age = age;
}else {
System.out.println("您输入的年龄有误");
}
}
}
public class Test {
public static void main(String[] args) {
Student s = new Student();
//由于age被私有 所以要通过setter方法对age进行赋值
// s.age;
s.setAge(23);
//通过getter方法 获取age值
System.out.println(s.getAge());
}
}
一般会把成员变量使用private隐藏起来,对外就不能直接访问
提供public修饰的getter和setter方法暴露其取值和赋值
八、标准javaBean
javaBean也可以称为实体类(在现实生活中有对应个体),其对象可以用于在程序中封装数据。
一个标准的javaBean须满足如下书写要求:
- 成员变量使用public修饰。
- 提供成员变量对应的setXxx() / getXxx()方法。
- 必须提供一个无参构造器;有参构造器可写可不写。
public class JavaBeanTest {
//标准javaBean构建步骤
//1、成员变量私有
private String name;
private Double salary;
//2、提供成员变量对应的setXxx()和getXxx()方法。
//快捷键 alt + Ins
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
//3、构造无参构造器,默认为无参构造器,所以不需要额外构建。
}
九、面向对象基础案例
public class MovieTest {
public static void main(String[] args) {
//1、设计电影类
//2、创建三个电影对象,封装电影信息
//3、定义一个电影类型的数组存储3部电影,简化写法2、3
Movie[] movies = new Movie[3];
movies[0] = new Movie("《长津湖》",9.5,"吴京");
movies[1] = new Movie("《我和我的父辈》",9.0,"吴京");
movies[2] = new Movie("《扑水少年》",8.0,"王川");
for (int i = 0; i < movies.length; i++) {
//将索引结果暂存在m中,再通过m调用方法获取信息
Movie m = movies[i];
System.out.println("----------------------------");
System.out.println("电影名:" + m.getName());
System.out.println("评分:" + m.getScore());
System.out.println("主演:" + m.getActor());
System.out.println("----------------------------");
}
}
}
public class Movie {
//电影类
private String name;
private Double score;
private String actor;
//alt + Ins
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public String getActor() {
return actor;
}
public void setActor(String actor) {
this.actor = actor;
}
public Movie() {
//无参数构造器
}
public Movie(String name, Double score, String actor) {
//有参数构造器
this.name = name;
this.score = score;
this.actor = actor;
}
}
案例过程解析:
首先执行main方法,将main方法提到栈内存中,开始执行第一行代码,在main方法中开辟一块区域给变量movies,并在堆内存中开辟一块区域存放Movie类型的数组对象,将数组对象的地址赋给变量movies存储,使变量指向对象在堆内存中的地址,再在堆内存中依次创建三个新的对象,并将地址依次赋给数组对象中存储,使数组对象依次指向三个新对象
十、 成员变量和局部变量的区别
成员变量是类中的成员属性,局部变量是方法中定义的变量,比如main方法。
public class Movie {
//成员变量
private String name;
private Double score;
private String actor;
}