目录
1. 初识面向对象【了解】
1.1 面向过程
面向过程概念:是一种编程思想,就是分析出解决问题所需要的步骤,然后用方法把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
通过下面造车案例了解
假设我要造辆车,就需要以下步骤完成:
step1. 设计画图
step2. 找矿=>挖矿=>炼铁=>打铁=>制作车体
step3. 生产发动机、变速箱等
step4. 养牛=>庖丁解牛=>(如果没解好,牛皮破了—>重养)牛皮=>座椅
step5. 种树=>炼橡胶=>轮胎
step6. 组装
step7. 测试
1.2 面向对象
面向对象概念:就是一种编程思想,是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
通过下面造车案例了解
假设我要造辆车,就需要以下步骤完成:
step1. 设计画图=>保时捷设计所
step2. 原材料:发动机=>秋名山神车五菱发动机;变速箱=>巨力三轮车24速手动变速箱;轮胎=>青岛双星牌;底盘=>兰博基尼大牛;座椅=>香奈儿
step3. 组装=>东莞代工厂
step4. 贴牌=>Step5. 测试=>C-NCAP=>10星安全法兰保牌
通过下面五子棋案例了解
例如五子棋,面向过程的设计思路就是首先分析问题的步骤:
1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子
6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。
把上面每个步骤用分别的函数来实现,问题就解决了。
而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为 1、黑白双方
这两方的行为是一模一样的,2、棋盘系统,负责绘制画面。3、规则系统,负责判定诸如犯规、输赢等。
第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)
棋子布局的变化,棋盘对象接收到了棋子的i变化就要负责在屏幕上面显示出这种变化
同时利用第三类对象(规则系统)来对棋局进行判定。
可以明显地看出,面向对象是以功能来划分问题,而不是步骤。
同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中
很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。
而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。
功能上的统一保证了面向对象设计的可扩展性。比如我要加入悔棋的功能
如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要改动
甚至步骤之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了
棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及
同时整个对对象功能的调用顺序都没有变化,改动只是局部的。
那么,面向对象和面向过程哪种好呢?各有各个好
面向对象和面向过程都是软件开发的一种编程思想,要真正的理解一种编程思想,或者说应用在实际的开发设计中,并不是看几本书,听我说几句就能搞定的事情,需要先了解,在实际开发中应用,这样不断的思考分析、积累,从而达到理解。
举个事例,现在我手上接了一个500W的项目,接下来我需要完成这个项目,现在我有两个选择:第一是自己一人开发;第二是组建团队或者说外包。
第一,自己一个人独立开发。那么我需要做的事情可能就包括了:需求搜集、分析,原型设计,项目架构设计,编码实现,项目测试,项目实施等等。其中每一件事情都必须亲力亲为,感觉心里倒也踏实,不过这个过程可能是这样:
哈哈,接了个单高高兴兴敲代码!!
丫,咋还出bug了呢,纳尼...
不会吧,我都调试3个通宵了...
糟糕,我要崩溃了...
算了,我想睡一会儿(安息吧!)
第二,组建团队开发
有了自己的团队之后,就可以不用再陪客户喝茶、吃饭、聊天、(售前售后);不用再排异常、找bug、调网络(攻城狮);不用再反复修改设计方案版本(射鸡湿)。那么我现在做什么呢?当然是数钱啦(嘿嘿...纯洁的笑容)。
其实我现在做的就是管理好我的团队,分配好任务,控制项目进度等,在整个过程中充当指挥者的角色。
上面的两个事例第一种是面向过程的做事方式,第二种是面向对象的做事方式。通过这样的事例从面向对象某一些方面的特征来简单的让大家有一个认识而已,更多的内容需要通过后面章节来逐步了解、加深。
2. 类与对象
2.1 类和对象【了解】
比如做一个学生管理系统的项目 :
现实生活中,学生过来学习要填写一个学员信息表。纸质文档不利于后期查询和维护,并且处理数据的效率极其底下。
所以需要做一个系统,那么,做一个系统我们需要做什么事情呢?
3.2 类和对象【理解】
什么是类?
类是具备某些共同特征的实体的集合,是对所具有相同特征实体的抽象, 例如人类、车类、星球类,动物类, 猪类等。
什么是对象?
对象是类的实例,简单的认为对象就是类中具体的个体。
用一个例子给你说明一下他们的关系:
比如“人类”就是一个类,那么具体的某个人“张三”就是“人类”这个类的对象,而“名字、年龄”等信息就是对象的属性,人的动作比如“吃饭、穿衣”等就是对象的方法。
类和对象的关系请看下面的图例:
类 =>【模板】
创建对象 =>【复制模板】
java语言世界:万事万物皆对象
通常都会将对象划分为两个部分,即动态部分(方法)与静态部分(成员变量)。
静态部分:顾名思义就是不能动的部分,这个部分被称为“属性”,如一个人,它包括高矮、胖瘦、性别、年龄等属性——成员变量。
动态部分:人可以哭泣、微笑、说话、行走,这些是这个人具备的行为(动态部分)——方法。
3. 设计类【重点】
3.1 设计类
设计类语法:【设计类,业务类,没有main方法 => 设计模板】
public class 类名 {
// 可编写 0 到 n 个成员变量
[修饰符] 数据类型 变量名1;
[修饰符] 数据类型 变量名2;
// 可编写 0 到 n 个成员方法
[修饰符] 返回值类型 方法名称(参数) {
//方法体
}
}
设计类要求:
1.类名,大驼峰,见名知意,不能以jdk中存在的类命名
2.成员变量名和方法名,小驼峰,见名知意
3.在类名、方法名、成员变量名上面写文档注释
示例 : 设计一个学生类(模板))
/**
* 学生类
*/
public class Student {
/** 姓名 成员变量 是类的属性,静止的部分 */
String name;
/** 年龄 成员变量 是类的属性,静止的部分 */
int age;
/**
* 学习方法
* 是类的行为,是动态的部分
*/
public void study() {
System.out.println("good good study ,day day up !");
}
}
3.2 修饰符【了解】
3.2.1修饰符概念
对Java当中的,类,变量,方法,构造方法等等.....进行修饰,赋予被修饰内容特殊意义。
3.2.2 修饰符分类【了解】
3.2.2.1 类修饰符
public(访问控制符): 将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类。
abstract:将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现。
final:将一个类申明为最终(即非继承类),表示他不能被其他类继承。
默认不写:默认的修饰符,只有在相同包中的对象才能使用这样的类。
3.2.2.2 成员变量修饰符
public(公共访问控制符):指定该变量为公共的,他可以被任何对象的方法访问。
private(私有访问控制符):指定该变量只允许自己的类的方法访问,其他任何类(包括子类)中的方法均不能访问。
protected(保护访问控制符):指定该变量可以别被自己的类和子类访问。在子类中可以覆盖此变量。
默认不写 :在同一个包中的类可以访问,其他包中的类不能访问。
final:最终修饰符,指定此变量的值不能变。
static(静态修饰符):指定变量被所有对象共享,即所有实例都可以使用该变量。变量属于这个类。
transient(过度修饰符):指定该变量是系统保留,暂无特别作用的临时性变量。
volatile:指定该变量可以同时被几个线程控制和修改。
3.2.2.3 方法修饰符
public(公共控制符: 指定此方法可以被自己和其他的类访问
private(私有控制符):指定此方法只能有自己类等方法访问,其他的类不能访问(包括子类)
protected(保护访问控制符):指定该方法可以被它的类和子类进行访问。
final:指定该方法不能被重载。
static:指定不需要实例化就可以激活的一个方法。
synchronize:同步修饰符,在多个线程中,该修饰符用于在运行前,对他所属的方法加锁,以防止其他线程的访问,运行结束后解锁。
native:本地修饰符。指定此方法的方法体是用其他语言在程序外部编写的
4.0创建对象和成员变量赋值取值【重点】
设计一个测试类,测试类命名,XxxTest,包含main方法,在测试类的main方法中,写以下代码:
创建对象、对象赋值、对象取值打印。
4.1创建对象
创建对象语法:
类名 对象名 = new 类名();
例如:
public class StudentTest {
public static void main(String[] args) {
// 1. 创建对象(相当于复制模板): 语法:类名 对象名 = new 类名();
Student student = new Student();// 必须声明一个Student类型的变量保存当前对象
}
}
4.2给对象成员变量赋值
给对象成员变量赋值语法:
对象名.成员变量 = 值; // 注意:值和成员变量数据类型必须一致
例如:
public class StudentTest {
public static void main(String[] args) {
// 1. 创建对象(相当于复制模板): 语法:类名 对象名 = new 类名();
Student student = new Student();// 必须声明一个Student类型的变量保存当前对象
// 2. 对象赋值(填写信息) 语法:对象名.成员变量 = 值;
student.name = "苍老师";
student.age = 37;
}
}
4.3对象取值和对象调用实例方法
/* 对象取值语法:
对象名.成员变量 ;
对象调用实例方法:
对象名.方法名(…);
例如:
**/
public class StudentTest {
public static void main(String[] args) {
// 1. 创建对象(相当于复制模板): 语法:类名 对象名 = new 类名();
Student student = new Student();// 必须声明一个Student类型的变量保存当前对象
// 2. 对象赋值(填写信息) 语法:对象名.成员变量 = 值;
student.name = "苍老师";
student.age = 37;
// 3. 对象取值(相当于查询信息) 语法:对象名.成员变量;
System.out.println(student.name);// "苍老师"
System.out.println(student.age);// 37
// 4. 对象调用非static(实例)方法 语法:对象名.方法名(...);
student.study();
}
}
4.4堆栈内存图分析代码(理解):
下面使用堆栈内存图来解释一下上面代码的流程和存储。从下图中可以看到:
① 每创建一个对象都会在堆内存中开辟一块空间,并且这块空间中具有和类(模板)中一样的成员。
② 每一个对象都被栈中的一个变量所指向,所以操作栈中的变量(student)就如同操作堆中的对象。
③ student.name = "苍老师";其实是把字符串值赋值给student变量指向的堆中的name字段上的,而不是设置给类的,所以我们在分析代码的时候,看到new Student()对象应该立马想到在堆中有一个对象。
5.构造方法(Constructor)(重点)
5.1 构造方法引入
先来看上面写的代码
public class StudentTest {
public static void main(String[] args) {
// 1. 创建对象(相当于复制模板): 语法:类名 对象名 = new 类名();
Student student = new Student();// 必须声明一个Student类型的变量保存当前对象
// 2. 对象赋值(填写信息) 语法:对象名.成员变量 = 值;
student.name = "苍老师";
student.age = 37;
// 3. 对象取值(相当于查询信息) 语法:对象名.成员变量;
System.out.println(student.name);// "苍老师"
System.out.println(student.age);// 37
}
}
代码中创建对象后赋值,存在这样的一个问题:如果创建多个对象赋值的话,代码会非常麻烦,所以,我们想办法来优化一下代码,想在创建对象的同时直接赋值,那么怎么办呢?通过构造方法来实现。
其实构造方法我们已经在使用了,只不过上面还没有提出来,来一起看下面代码:
new Student();创建一个学生类的对象
上面代码本质是调用Student中的无参数的构造方法!
5.2 什么是构造方法
概念:就是一个类中的新结构,是类的成员。
1. 构造方法的结构和普通方法类似,但是和普通方法完全不同两个代码块;
2. 构造方法也是方法,意味着使用了构造方法,方法会执行,也能完成功能
3. 构造方法就是一个代码块【就是一个结构 ,构造方法和 字段 方法一样都是一个类中的成员之一】
4. 构造方法也该存在于类的结构体中
5.3 构造方法特点【掌握】
1. 每一个类中都至少有一个构造方法;
2. 如果没有看到(显示的),那么存在一个隐式的无参数的构造方法;
3. 如果一个类中有显示的构造方法,那么隐式的无参的构造方法就不存在了;
5.4 构造方法的作用【掌握】
作用是:在创建对象的时候,直接给对象成员变量赋值,可以简化代码
注意:
- 只能在创建的时候赋值,不能给已经创建的对象赋值。
- 构造方法一旦通过 new调用,都表示在堆中创建新对象,只要看到new,都表示在堆中创建新对象。
5.5 构造方法语法【掌握】
构造方法声明语法:
1. 构造方法的名字和类名完全一致(包括大小写完全一致)。
2. 没有返回值类型(void也不行)。
3. 构造方法方法体不能返回任何的值(即不能在方法体中return 值)。
4. 其他的和普通方法类似 ,可以有修饰符(public、protected、private、默认),可以有形参列表。
5. 构造方法必须有方法体。
6. 构造方法不能有任何非访问性质的修饰符修饰,例如 static、final、synchronized、abstract等都不能修饰构造方法。
构造方法使用语法:
new 类名();// 调用无参构造
new 类名(...);// 调用有参构造
例如:
new User();// 表示在调用User的无参构造
注意:new Student() 这个整体既是一个Student对象,又是调用的Student的无参数构造方法。
设计类语法:
public class 类名 {
小驼峰成员变量 (字段);
修饰符 Xxx(...){// 构造方法大驼峰类名
构造方法的方法体
};
修饰符 xxxXxx(...){// 普通方法小驼峰
普通方法 体
}
}
代码案例:
public class User {
/** 姓名 */
String name;
/** 年龄 */
int age;
/**
* 无参构造
*/
public User() {
System.out.println("User无参构造...");
}
/**
* 有参构造
* 形参个数由需求决定
*/
public User(String n, int a) {
name = n;// 将传入的n的值赋值给成员变量name
age = a;// 将传入的a的值赋值给成员变量age
System.out.println("User有参构造...");
}
public void playGame(String str) {
System.out.println(name + " 喜欢:" + str);
}
}
5.6 构造方法注意事项【了解】
1. 普通方法不要和类名一致,行业默认规则。
2. 普通方法(Method)和构造方法(Constructor)是不同的两种结构。
2.1 普通方法的调用 : 3种
2.1.1 类名.方法名(…); --有static修饰的
2.1.2 对象名.方法名(…); --没有static修饰的
2.1.3 方法名(…); --同一个类里面都有static或都没有static修饰
2.2 构造方法的调用 :new 类名(...);(目前为止)
5.7 构造方法小结【掌握】
给对象成员变量赋值方式:
1. 对象名.成员变量 = 值;// 值和成员变量数据类型一致
2. 有参构造: new 类名(...);// 实参和成员变量数据类型一致
对象取值方式:对象名.成员变量
注意:
有参构造不能给已经创建的对象赋值,如果必须给已经创建的对象重新赋值,只能通过:对象名.成员变量 = 值;的方式实现。
5.8 有参构造和无参构造使用场景:【重点】
当对象需要赋值的成员变量 很多 的时候,用:无参构造创建对象,然后用 对象名.成员变量 = 值; 方式赋值。
当对象需要赋值的成员变量 少 的时候,用:有参构造创建对象直接赋值即可。
5.9 内存分析图【了解】
6.匿名对象【了解】
6.1 匿名对象引入
案例:
public static void main(String[] args) {
// 1. 创建对象
Student stu = new Student();
// 2. 对象赋值
new Student().name = "苍老师"; // 其实这就是匿名对象
// 3. 对象取值
System.out.println(new Student().name);// null
}
6.2 什么是匿名对象
概念:匿名对象,就是创建的时候没有使用变量接收保存一个对象。
但是匿名对象本质也是一个对象(具体的值)
- int i = 10;// int数据类型,i变量是一个int值,是具体的一个数据。
- Student stu = new Student();// Student数据类型的stu变量是堆中的一个对象,也是一个数据。
6.3 匿名对象作用
可以节约资源,因为GC【垃圾回收器】会不定时回收匿名对象。
6.4 匿名对象使用场景
匿名对象一般用在:只需要使用一次的情况(如:调用一次非static修饰的普通方法、作为方法实参使用)
7.对象的生命周期(了解)
1. 对象的生命周期:就是对象从开始到结束的过程。
1.1开始 : new Student(),new的时候就开始了,在堆中。
1.2结束:
1.2.1 说法1(常见的说法):当对象失去所有的引用(没有变量再指向它了)。
1.2.2 说法2 :对象真正的被销毁(对象会在堆里面占用内存,当把对象的内存空间回收了),Java有自动垃圾回收机制(GC)。
不需要纠结究竟是什么时候结束,我们可以简单都认为是在失去引用的时候结束。