面向对象
1. 生活中什么是面向对象
面向对象:
想吃烤羊排
1. 去馕坑烤肉店
2. 两个人点一斤羊排
3. 等25分钟
4. 吃
5. 付款走人
面向过程:
自己做烤羊排
1. 从JD上买羊排,洋葱,大葱,姜,烧烤料,孜然粉,辣椒面
2. 解冻羊排,准备辅料
3. 切羊排,腌制,撒盐,腌制30分钟
4. 烤箱预热5分钟,220度
5. 烤制 25分钟 15分钟翻面
6. 吃!!!蘸料~~~
7. 收拾东西
从生活角度看面向对象:
找合适的人,做合适事
从生活角度看面向过程:
亲力亲为,自力更生,体验人生疾苦
代码中:
Arrays.toString();
Arrays.sort();
Arrays.binarySearch();
2. 类和对象
| 类 | 对象 |
|---|---|
| 人类 | 马云爸爸,麻花藤,乔布斯Jobs,科比 R.I.P |
| 狗类 | 王可可,忠犬八公,可可 |
| 汽车类 | 1949红旗,骚磊的Audi A4L 45TFSI,京A00001 |
| 电脑类 | 我的W541,我的MBP,我的DELL灵越 |
类:
对于一类事物的统称,对当前事物的一些描述,属性描述和行为描述
对象:
独立,唯一,特殊的个体
3. Java中定义类的格式
/*
class ClassName {
// 属性描述
// 行为描述
}
要求:
1. ClassName要求符合大驼峰命名法,并且要做到见名知意!!!
2. 属性描述,是用于描述当前类拥有的一些特征,这里可以使用变量
该变量有一个特定的名字【成员变量】 Field
3. 行为描述,是用于描述当前类可以做到一些事情,这里使用方法。
该方法有一个特定的名字【成员方法】Method
*/
3.1 Java中定义类【成员变量】
/**
* 这里定义的是一个Person类
*
* @author Anonymous
*/
class Person {
// 属性描述,这里使用成员变量 Field
// 使用String类型来描述Person类的姓名属性
String name;
// 使用int类型数据描述Person类的年龄属性
int age;
// 使用char类型数据描述Person类的性别属性
char gender;
}
3.2 Java中定义类【成员方法】
// 使用方法描述Perosn类的吃饭行为
public void eat(String food) {
System.out.println("吃" + food);
}
// 使用方法描述Person类的睡觉行为
public void sleep() {
System.out.println("说出来你可能不行,是床先动的手~~~");
}
// 使用方法描述Person类的打豆豆行为
public void daDouDou() {
System.out.println("吃饭,睡觉,打豆豆");
}
/*
特征:
1. 目前没有使用static关键字
2. 方法和之前所学方式形式一致,同样拥有三大元素 返回值,方法名和形式参数列表
Shift + Alt + A
*/
4. 类对象使用
4.1 Java中创建类对象的形式
/*
new 对象!!!
*/
// 获取一个扫描器的类对象!!!
Scanner sc = new Scanner(System.in);
/*
java.util.Scanner :
数据类型,Scanner类型。创建的【变量】是Scanner的类对象,同时也是一个引用
数据类型
sc :
类对象,变量
Scanner的类对象,sc是对象名
new :
申请内存的【堆区】空间,并且清理整个空间中的所有数据。
代码中,只有有new关键字,一定会使用到内存的堆区空间,并且是新的内存空间。
Scanner(System.in) :
1. 这里是一个方法,因为有小括号
2. 方法名字和类名一致
3. 该方法称之为构造方法,Constructor 构造方法
总结:
类名 对象名 = new 构造方法(所需参数);
*/
// 这里创建了一个Person类对象,对象名person
Person person = new Person();
System.out.println(person);
/*
* com.qfedu.a_object.Person@15db9742
* com.qfedu.a_object 完整的包名
* Person 数据类型,这里创建的对象是一个Person类对象
* @15db9742 当前类对象在内存空间的中首地址!!!十六进制展示方式
*/
Person person1 = new Person();
System.out.println(person1);
/*
* com.qfedu.a_object.Person@6d06d69c
* 发现第二个Person类对象 person1空间首地址6d06d69c 和第一个对象不一致
* 这里就意味着两个对象的空间首地址不一致,不是同一个对象!!!
*/
4.2 Java中使用类对象调用成员变量
/*
int[] arr = new int[10];
获取数组的容量:
arr.length
获取一个数组中【的】length属性
格式:
对象名.属性名/成员变量名;
. ==> 的
可以操作取值或者赋值操作。
*/
// 通过Person类对象 person调用类内的成员变量
// 【赋值】Person类对象 person中对应的成员变量
person.name = "骚磊";
person.age = 16;
person.gender = '男';
// 【取值】展示Person类对象 person中保存的成员变量数据
System.out.println("Name:" + person.name);
System.out.println("Age:" + person.age);
System.out.println("Gender:" + person.gender);
4.3 Java中使用类对象调用成员方法
/*
得到了一个Scanner类对象sc
Scanner sc = new Scanner(System.in);
使用过以下方法:
sc.nextInt();
sc.nextFloat();
sc.nextLine().charAt(0);
格式:
类对象.方法名(必要的参数);
. ==> 的
*/
5. 类对象内存分析图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0m9zXaRS-1581752352350)(.\img\类对象内存分析图.png)]
6. 类对象内存转移问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JhC3AFCS-1581752352351)(.\img\类对象内存转移问题分析图.png)]
7. 构造方法 Constructor
7.1 Java编译器提供的默认的构造方法
问题:
发现在代码中没有显式定义构造方法,为什么可以使用一个无参数的构造方法?
Java反编译工具:
javap -c -l -private XXXX.class
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iJjEitvw-1581752352351)(.\img\反编译之后内容.png)]
通过反编译工具,发现了一些不存在与代码中的内容,而这段内容就是Java编译器为了方便程序开发,提供的一个必要的无参数构造方法。
Java编译器如果发现当前class没有显式自定义构造方法,会默认提供一个无参数构造方法给予使用。
如果Java编译器发现在代码中出现了任何一个构造方法,就不会再提供对应的无参数构造方法。
7.2 自定义使用构造方法
构造方法功能:
初始化当前类对象中保存的成员变量数据。
目前创建对象的方式;
new 构造方法(有可能需要的参数);
new:
1. 根据构造方法提供的数据类型申请对应的堆区内存空间。
2. 擦除整个空间中所有的数据。
构造方法:
初始化在当前内存堆区空间的成员变量对应的数据
格式:
public 类名(初始化形式参数列表) {
初始化赋值语句;
}
要求:
1. 无论什么时候一定要留有一个无参数构造方法备用
2. 根据所需情况完成构造方法参数选择
3. 一个class可以有多个构造方法【方法的重载】
8. 方法的重载
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7sS5AZkH-1581752352352)(.\img\多个构造方法.png)]
总结:
1. 所有的方法名字都是一致的!!!
2. 所有的方法参数都是不一样的!!!
3. 同一个类内!!!
这就是方法的重载!!!
优点:
1. 简化了开发压力
2. 简化了记忆压力
3. 更快捷的调用方法,同时又满足了不同的情况!!!
规范:
重载情况下,在同一个类内,不可以出现相同方法名和相同参数数据类型的方法!!!
基本原理:
方法名一致的情况下,通过形式参数列表数据类型的不同来选择不同的方法执行。
反射 ==>Constructor Method
9. this关键字
9.1 this关键字特征
package com.qfedu.a_object;
class SingleDog {
public SingleDog() {
System.out.println("Constructor : " + this);
}
public void test() {
System.out.println("Method Called : " + this);
}
}
/*
* this关键字特征:
* this关键字表示调用当前方法的类对象,
* 或者是当前构造方法中初始化的类对象
*/
public class Demo4 {
public static void main(String[] args) {
SingleDog singleDog = new SingleDog();
System.out.println("Instance : " + singleDog);
singleDog.test();
}
}
9.2 解决就近原则问题
/**
* 使用String类型参数和int类型参数初始化类对象成员变量数据
*
* @param name String类型数据 用于初始化name属性
* @param age int类型数据 用于初始化age属性
*/
public Cat(String name, int age) {
name = name;
age = age;
System.out.println("带有两个参数的构造方法");
}
/*
我们期望使用比较直观的参数名方式,告知调用者这里需要的数据到底是什么?
但是会导致【就近原则】问题
在构造方法中所有的name,age都会被看作是一个局部变量,而不是成员变量
期望:
可以有一种参数方式告知编译器这里操作的是一个成员变量,而不是一个局部变量!!!
*/
--------------------------修改方式----------------------------------
/**
* 使用String类型参数和int类型参数初始化类对象成员变量数据
*
* @param name String类型数据 用于初始化name属性
* @param age int类型数据 用于初始化age属性
*/
public Cat(String name, int age) {
/*
* 使用this关键字明确告知编译器这里使用的是一个成员变量,而不是
* 局部变量,解决就近原则问题
*/
this.name = name;
this.age = age;
}
9.3 this关键字调用其他构造方法【之后讲解】
10. 成员变量和局部变量的对比
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 作用 | 属性描述,描述当前类拥有哪些属性 | 在方法运行的过程中保存必要的数据 |
| 位置 | 成员变量定义在class大括号以内,其他大括号之外 | 在方法大括号或者代码块大括号以内 |
| 初始值 | 成员变量在没有被构造方法赋值的情况下,是对应数据类型的"零"值 | 未赋值不能参与除赋值之外的其他运算。 |
| 作用域 | 成员变量存储于类对象中,在内存的堆区,哪里持有当前类对象的空间首地址,作用域就在哪里 | 有且只在当前大括号以内 |
| 生存期 | 成员变量的生存期是随着类对象的创建而开始,当对象被JVM的GC销毁时,成员变量的生存期终止 | 从定义位置开始,到当前大括号结束 |
【补充知识点 "零"值】
new关键字申请内存空间,并且擦除的一干二净
对应每一个数据类型的"零"值
基本数据类型
byte short int 0
long 0L
float 0.0F
double 0.0
char '\0' ==> nul
boolean false
引用数据类型
全部为null
Person person null
String str null
int[] arr null
null
是内存地址中非常特殊的东西!!!
【补充知识点 JVM的GC机制 简述】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sTr58XN4-1581752352352)(.\img\图书管理员简述回收机制.png)]
Java中内存管理制度GC就类似于图书管理员身份
1. 在单位时间内,检查当前Java程序使用的内存中是否存在无主内存。
2. 标记无主内存,多次标记的情况下,会将无主内存释放,归还内存空间。
好处:
1. 让程序员管理内存更加方便。
2. 内存管理是完全自动化
劣势:
1. 内存回收效率不高。
2. 内存管理出现泄漏问题。
11. 二分法查找
特征:
1. 要求查询的数组必须是一个经过排序之后的数组
2. 多个指定数据的情况下,无法告知到底是第几个数据出现
3. 没有找到数据返回负数
演示:
1 3 5 7 9 11 13 15 17 19
例如:
查询元素 13的下标位置
第一步:
中间下标元素是 下标为4 元素值=9
最小下标为0
最大下标为9
9 < 13
需要修改最小下标 ==> 中间下标 + 1 ==> 5
第二步:
中间下标元素是 下标为7 元素值=15
最小下标为5
最大下标为9
15 > 13
需要修改最大下标 ==> 中间下标 - 1 ==> 6
第三步:
中间下标元素是 下标为5 元素值=11
最小下标为5
最大下标为6
11 < 13
需要修改最小下标 ==> 中间下标 + 1 ==> 6
第四步:
得到结果
/**
* 二分法查找算法
*
* @param sortedArray 这里要求是一个int类型数组,并且是进过排序之后的升序数组
* @param find 需要查询的元素
* @return 返回值大于等于0找到元素下标位置,没有找返回-1
*/
public static int halfSearch(int[] sortedArray, int find) {
int minIndex = 0;
int maxIndex = sortedArray.length - 1;
int mid = (minIndex + maxIndex) / 2;
while (minIndex <= maxIndex) {
if (sortedArray[mid] > find) {
maxIndex = mid - 1;
} else if (sortedArray[mid] < find) {
minIndex = mid + 1;
} else {
return mid;
}
mid = (minIndex + maxIndex) / 2;
}
return -1;
}
本文深入浅出地介绍了面向对象编程的基本概念,包括类与对象、构造方法、成员变量与成员方法的区别,以及如何在Java中定义和使用这些概念。通过生动的例子,如烤羊排的场景,帮助理解面向对象与面向过程的差异。
2611

被折叠的 条评论
为什么被折叠?



