概念
Thinking in java
所谓的面向对象是一种编程思想,通过这种思想可以把生活中的复杂事情变得简单化,从原来的执行者变成了指挥者。
面向对象是基于面向过程而言的。
我们经常说的面向对象的编程实现(OOP,Object Oriented Programming)
三大特征
- 封装性,把相关的数据封装成一个“类”组件
- 继承性,是子类自动共享父类属性和方法,这是类之间的一种关系
- 多态,增强软件的灵活性和重用性
类和对象
类
- Java语言最基本单位就是类,类似于类型
- 类是一类事物的抽象
- 可以理解为模板或者设计图纸
对象
每个对象具有三个特点:对象的状态,对象的行为和对象的标识
- 对象的状态用来描述对象的基本特征
- 对象的行为用来描述对象的功能
- 对象的标识是指对象在内存中都有一个唯一的地址值用来和其他对象区分开来
- 类是一类事物的抽象,对象是具体的实现
汽车类:
实现可以有奥迪汽车对象、有宝马汽车对象
类和对象的关系
计算机语言是用来描述现实世界事物的。
成员属性+成员方法
那怎么通过java语言描述?
通过类来描述事物,把事物的属性当做成员变量,把行为当做成员方法。
分析手机事物:
特征:颜色,尺寸,品牌,价格……
功能:打电话,发短信,听音乐……
类:手机类,抽取相同的特征和功能
对象:可以按照模板生产很多个手机,比如1号手机对象,包含特有的成员变量和成员方法
注意!类是一类事物的抽象,具体实践找对象
创建对象的流程
Person p = new Person();//短短这行代码发生了很多事情
1. 把Person.class文件加载进内存
2. 在栈内存中,开辟空间,存放变量p
3. 在堆内存中,开辟空间,存放Person对象
4. 对成员变量进行默认的初始化
5. 对成员变量进行显示初始化
6. 执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
7. 堆内存完成
8. 把堆内存的地址值赋值给变量p ,p就是一个引用变量,引用了Person对象的地址值
匿名对象
没有名字的对象,是对象的简化表示形式。
使用场景:
1、 当被调用的对象只调用一次时(多次会创建多个对象浪费内存)
Demo d = new Demo();
d.sleep();
d.game();
//这个d就是对象的名字。
也可以写成:
new Demo().show();//创建了一个对象调方法
new Demo().game();//又创建了一个对象调方法
类和对象的创建和使用
对象在内存中的存储
Java把内存分成5大区域,我们重点关注栈和堆。
- 一般来讲局部变量存在栈中,方法执行完毕内存就被释放
- 对象(new出来的东西)存在堆中,对象不再被使用时,内存才会被释放
- 每个堆内存的元素都有地址值
- 对象中的属性都是有默认值的
单一对象内存图
多个对象内存图
示例
三大特征·封装
概述
封装是指隐藏对象的属性和实现细节
仅仅对外提供公共的访问方式
优点:
private关键字
是一个权限修饰符,用于修饰成员变量和成员函数
被私有化的成员只能在本类中访问
示例
类中的private可通过 setXXX() 设置值 getXXX() 访问/获取值
自动添加公共访问方法
instanceof 关键字
A
B继承A
C继承B
A a=new C();
a instanceof C true
a instanceof B true
a instanceof A true
a instanceof Object true
instanceof 比较的是实例以及父类等等
和getClass()区别
getClass()比的是地址
a.getClass()==C.class true
a.getClass()==B.class false
三大特征·继承
概念
继承是面向对象最显著的一个特性
继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力
Java继承是使用已存在的类的定义作为基类/父类/超类,新类的定义可以增加新的数据或新的功能,也可以用父类的功能
但不能选择性地继承父类(超类,基类)。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用
特点
- 使用extends关键字
- 相当于子类把父类的功能复制了一份
- java只支持单继承→只能有一个爸爸
- 继承可以传递(爷爷,儿子,孙子的关系)
- 不能继承父类的私有成员
- 继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展(意义)
- 像是is a 的关系
- 子类重写父类的方法,其访问修饰符的范围必须大于等于父类,并且不能出现final
super关键字
- 通过super关键字可以使用父类的内容
- super代表父类的一个引用对象
- 如果在构造方法中使用,必须是第一条语句
this和super的区别
- this代表本类对象的引用,super代表父类对象的引用(父类如果是抽象类,调用构造函数进行初始化(不新建父类对象),父类如果不是抽象类,调用构造函数进行初始化并新建了一个父类对象)
- this用于区分局部变量和成员变量
- super用于区分本类变量和父类变量
- this.成员变量 this.成员方法() this( [参数] )代表调用本类构造方法
- super.成员变量 super.成员方法() super( [参数] ),代表调用父类构造方法
- this和super不可以同时出现在同一个构造方法里,因为他们两个只要出现都得放在第一行
方法重写Override
- 继承后,子类就拥有了父类的功能
- 那么在子类中,可以添加子类特有的功能也可以修改父类的原有功能
- 子类中方法的声明与父类完全一样时,会发生覆盖/复写/重写操作→重载:只有参数列表不同
- 方法的声明:包括方法的返回值,方法名和参数列表,完全一致
注意
- 父类中的私有方法不能被重写
- 子类重写父类方法时,修饰符要大于等于父类修饰符的权限
- 父类中的构造方法不能被子类继承
Overload/重载和Override/重写的区别
方法名相同且参数列表不同(与返回值类型无关,访问修饰符大于等于即可)→重载
返回值类型为基本类型或无返回值类型时必须相同、方法名相同且参数列表相同(访问修饰符大于等于即可)→重写
static(调用非静态必须实例化)
概念
是java中的一个关键字
用于修饰成员(成员变量和成员方法)
特点
- 随着类的加载而加载 / 类的资源
- 只加载一次,就会一直存在,直到类消失就一起消失了
- 优先于对象加载(同为类的静态代码块和静态变量按位置的先后顺序加载)
- 被所有对象所共享
- 可以直接被类名调用
- 静态资源不会被重写(无论是变量还是方法,都只会随着类的加载而加载)
静态调用关系
package cn.tedu.staticdemo;
//测静态的使用
public class Test1_Static2 {
public static void main(String[] args) {
}
}
//创建Student类
class Student{
//普通资源:调用啥资源都可以
String name;
public void eat() {
//1、非静态调用静态 -- 能!!!
System.out.println(country);
//2、非静态调用非静态 -- 能!!!
System.out.println(name);
System.out.println("正在吃饭");
}
//静态资源:静态资源只能调用静态资源
static String country;
static public void study() {
//1、静态调用非静态 -- 不能!!
// System.out.println(name);
//2、静态调用静态 -- 能!!
System.out.println(country);
System.out.println("都在学习");
}
}
final(被修饰的内容不能改)
概念
1、 是java提供的一个关键字
2、 final是最终的意思
3、 final可以修饰类,方法,成员变量
初衷是因为:java出现了继承后,子类可以更改父类的功能,当父类功能不许子类改变时可以利用final关键字修饰父类
特点
- 被final修饰的类,不能被继承
- 被final修饰的方法,不能被重写(重写会报错,因此子类无法重写父类的方法,但可以重载;子类与父类完全一致的静态资源也不会被重写,但不会报错,被认为是两个无关的方法,如下图向上造型,调用的方法还为父类的方法(证明该方法未被重写),b3调用的则是自己的method2())
- 被final修饰的变量是个常量,不能被改变
- 常量的定义形式:final 数据类型 常量名 = 值
示例
三大特征·多态
概念
多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。
主要是指同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
好处是可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准
狗有两种形态:狗和小动物
特点
- 多态的前提是继承
- 要有方法的重写
- 父类引用指向子类对象,如:Animal a = new Dog(); -- 小到大,向上转型
- 多态中,编译看左边,运行看右边
查找类:Ctrl+Shift+t
查看继承结构:Ctrl+t
为什么使用多态
- 多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法
- 提高了程序的扩展性和可维护性
多态的成员使用
- 成员变量:使用的是父类的
- 成员方法:由于存在重写现象所以使用的是子类的
- 静态成员:随着对象而存在,谁调用的就返回谁的
向上转型和向下转型
在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。
在应用中就存在着两种转型方式,分别是:向上转型和向下转型。
比如:父类Parent,子类Child
向上转型
父类的引用指向子类对象
Parent p=new Child();
说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类的方法就根据这个引用指向调用子类重写方法
向下转型(较少)
子类的引用的指向子类对象,过程中必须要采取到强制转型。
Parent p = new Child();//向上转型,此时,p是Parent类型
Child c = (Child)p;//此时,把Parent类型的p转成小类型Child
//其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的
说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能
JAVA加载顺序
参考示例
具体代码
输出:
- 父类的静态成员>子类的静态成员>父类的非静态成员>父类的构造方法>子类的非静态成员>子类的构造函数>局部代码
- 静态成员:静态代码块和静态变量按先后顺序加载,静态方法不调用不执行
- 非静态成员: 非静态代码块和非静态变量按先后顺序加载,非静态方法不调用不执行
- 非构造方法无论静态与否,不调用不执行
权限修饰符
用来控制一个类,或者类中的成员的访问范围。
作用范围