Java面向对象学习的三条主线
1.java类及类的成员属性,方法,构造器,代码块,内部类
2.面向对象的三大特征:封装性,继承性,多态性,(抽象性)
3· 替他关键字:this super static final abstract interface package import等
人把大象装进冰箱”
面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。
把冰箱门打开
② 抬起大象,塞进冰箱
② 把冰箱门关闭
2.面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
人{
打开(冰箱){
冰箱.开开();
}
抬起(大象){
大象.进入(冰箱);
}
关闭(冰箱){
冰箱.闭合();
}
}
冰箱{
开开(){}
闭合(){}
}
大象{
进入(冰箱){
}
}
三、面向对象的两个要素:
类:对一类事物的描述,是抽象的、概念上的定义,对物体的行为和属性
对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
>面向对象程序设计的重点是类的设计
>设计类,就是设计类的成员。
类的主要成员是 属性,方法
属性:控制对应类里面的成员变量(field)=字段,域
方法:控制对应类里面的方法(函数)
创建一个类
在第一个方法中调用调用它
package com.atguigu.java;
一、设计类,其实就是设计类的成员
属性 = 成员变量 = field = 域、字段
方法 = 成员方法 = 函数 = method
创建类的对象 = 类的实例化 = 实例化类
二、类和对象的使用(面向对象思想落地的实现):
1.创建类,设计类的成员
2.创建类的对象
3.通过“对象.属性”或“对象.方法”调用对象的结构
三、如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。
四、对象的内存解析
/
//测试类
类中属性(变量)的使用
属性(成员变量) vs 局部变量
相同点
1.1 定义变量的格式:数据类型 变量名 = 变量值
1.2 先声明 ,后使用
package com.atguigu.java;
/*
* 类中方法的声明和使用
*
* 方法:描述类应该具有的功能。
* 比如:Math类:sqrt()\random() \...
* Scanner类:nextXxx() ...
* Arrays类:sort() \ binarySearch() \ toString() \ equals() \ ...
*
* 1.举例:
* public void eat(){}
* public void sleep(int hour){}
* public String getName(){}
* public String getNation(String nation){}
*
* 2. 方法的声明:权限修饰符 返回值类型 方法名(形参列表){
* 方法体
* }
* 注意:static、final、abstract 来修饰的方法,后面再讲。
*
* 3. 说明:
* 3.1 关于权限修饰符:默认方法的权限修饰符先都使用public
* Java规定的4种权限修饰符:private、public、缺省、protected -->封装性再细说
*
* 3.2 返回值类型: 有返回值 vs 没有返回值
* 3.2.1 如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用
* return关键字来返回指定类型的变量或常量:“return 数据”。
* 如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要
* 使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。
*
* 3.2.2 我们定义方法该不该有返回值?
* ① 题目要求
* ② 凭经验:具体问题具体分析
*
* 3.3 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
*
* 3.4 形参列表: 方法可以声明0个,1个,或多个形参。
* 3.4.1 格式:数据类型1 形参1,数据类型2 形参2,...
*
* 3.4.2 我们定义方法时,该不该定义形参?
* ① 题目要求
* ② 凭经验:具体问题具体分析
*
* 3.5 方法体:方法功能的体现。
*
* 4.return关键字的使用:
* 1.使用范围:使用在方法体中
* 2.作用:① 结束方法
* ② 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
* 3.注意点:return关键字后面不可以声明执行语句。
*
* 5. 方法的使用中,可以调用当前类的属性或方法
* 特殊的:方法A中又调用了方法A:递归方法。
* 方法中,不可以定义方法。
*/
public class CustomerTest {
public static void main(String[] args) {
Customer cust1 = new Customer();
cust1.eat();
//测试形参是否需要设置的问题
形参在不确定的情况下效果很好(可以更改),如果直接写到方法内部就无法再次更改数据;
2,局部变量(方法内的变量)都在栈空间里面。
当方法执行完后里面的局部变量会弹出栈。
形参也在里面栈里面
堆:我们把new出来的结构(比如数组,对象)加载在堆空间里面。补充对象的属性加载在堆空间中。
当main方法结束后对象也会弹出栈空间,对象弹出后相对应的它里面的属性也会被垃圾回收
(没有创建这个类的对象)在main方法下调用一个方法,这个方法必须是静态方法
方法的使用中,可以调用当前类的属性或方法
特殊的:方法A中又调用了方法A:递归方法。
方法中,不可以定义方法。、
关于重载
在同一个类中允许有同名的方法,只要形参,(参数)不同即可,位置不同也是重载,只和参数有关系,和修饰符之类无关,
也和形参名字无关
因为在一个函数中要实现的功能的类型不同,所以形参类型需要修改
可变形参的方法
1,jdk5以后新增的内容
2,具体使用
2.1可变个数的格式;(数据类型. . . 变量名)
2.2当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,。。。
2.3 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
2.4 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存。
2.5 可变个数形参在方法的形参中,必须声明在形参末尾
2.6 可变个数形参在方法的形参中,最多只能声明一个可变形参。
关于变量的赋值
如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
方法参数的值传递机制
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。(因为方法执行完局部变量会消失)
如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。(虽然局部变量会消失,但是引用数据类型会在堆里面)
归递方法
递归方法的使用(了解)
1.递归方法:一个方法体内调用它自身。
2. 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循
在多重递归中,会先将其一个归递方法完。在归递下一个方法。
总结:属性赋值的先后顺序
① 默认初始化
② 显式初始化
③ 构造器中初始化
④ 通过"对象.方法" 或 "对象.属性"的方式,赋值
以上操作的先后顺序:① - ② - ③ - ④
关于package关键字的使用
1,为了更好的实现项目中的类的管理,提供包的概念
2使用package声明类或接口所属的包,声明在源文件的首行
3,包属于标识符,遵循标识符的命名规则,规范(zzzxxxccc)“见名知意”
4没“.”一次,就代表一层文件目录
5,同一个包下,不能命名同名的接口和类,不同的包下可以命名相同的名字
import关键字的使用
import:导入
在源文件中显式的使用import结构导入指定包下的类、接口
2. 声明在包的声明和类的声明之间
3. 如果需要导入多个结构,则并列写出即可
4. 可以使用"xxx.*"的方式,表示可以导入xxx包下的所有结构
5. 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
6. 如果使用的类或接口是本包下定义的,则可以省略import结构
7. 如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示。
8. 使用"xxx.*"方式表明可以调用xxx包下的所有结构。但是如果使用的是xxx子包下的结构,则仍需要显式导入
String类型的类在long包下,不用导入
9. import static:导入指定类或接口中的静态结构:属性或方法。
super关键字的使用
* 1.super理解为:父类的
* 2.super可以用来调用:属性、方法、构造器
*
* 3.super的使用:调用属性和方法
*
* 3.1 我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用
* 父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
* 3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的
* 使用"super.属性"的方式,表明调用的是父类中声明的属性。
* 3.3 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的
* 使用"super.方法"的方式,表明调用的是父类中被重写的方法。
*
* 4.super调用构造器
* 4.1 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
* 4.2 "super(形参列表)"的使用,必须声明在子类构造器的首行!
* 4.3 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现
* 4.4 在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器:super()
* 4.5 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
方法的重写(override / overwrite)
*
* 1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
*
* 2.应用:重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。
*
* 3. 重写的规定:
* 方法的声明: 权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{
* //方法体
* }
* 约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
* ① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
* ② 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
* >特殊情况:子类不能重写父类中声明为private权限的方法
* ③ 返回值类型:
* >父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
* >父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类,不能大于父类类型
* >父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double)
* ④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体放到异常处理时候讲)
* **********************************************************************
* 子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写)。
*
* 面试题:区分方法的重载与重写
类里面只能书写子类的成员,但是方法可以
关于引用数据类型强转,当用父类接收子类的实例化对象,然后把这个类型进行强转为被实例化的的子类类型,对其总结就是
想要进行类型强转,其被强转的类型必须要有装转后的类型的方法和属性;(必须加载过这个类的属性和方法)
你想要强转成这个类必须要有这个类的属性和方法
A是父类b子类c是b子类
a类型想要转化为b类其必须要有b类的方法做法可以先将b类转化成a类让他有b类的属性和函数,或者c类转化成a类,间歇性的加载b类的函数和属性;
第一种是克隆一个对象,第二种是将对象的地址值赋给一个新的对象
java.lang.Object类
1.Object类是所有Java类的根父类
2.如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
3.Object类中的功能(属性、方法)就具有通用性。
属性:无
方法:equals() / toString() / getClass() /hashCode() / clone() / finalize()
wait() 、 notify()、notifyAll()
4. Object类只声明了一个空参的构造器
面试题:
final、finally、finalize的区别?
Object类中toString()的使用:
1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
2. Object类中toString()的定义:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
3. 像String、Date、File、包装类等都重写了Object类中的toString()方法。
使得在调用对象的toString()时,返回"实体内容"信息
4. 自定义类也可以重写toString()方法,当调用此方法时,返回对象的"实体内容"
面试题: == 和 equals() 区别
一、回顾 == 的使用:
== :运算符
1. 可以使用在基本数据类型变量和引用数据类型变量中
2. 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体
补充: == 符号使用时,必须保证符号左右两边的变量类型一致。
二、equals()方法的使用:
1. 是一个方法,而非运算符
2. 只能适用于引用数据类型
3. Object类中equals()的定义:
public boolean equals(Object obj) {
return (this == obj);
}
说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体
4. 像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是
两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
5. 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们
就需要对Object类中的equals()进行重写.
重写的原则:比较两个对象的实体内容是否相同.