面向对象的概念(一)
什么是面向过程,什么是面向对象
两者都是一种编程思想
1.面向过程:意思是我们要做任何事,都需要亲力亲为,强调的是过程
2.面向对象:相对于面向过程,我们可以由原来问题的执行者变为指挥者,进而把生活中很多复杂的问题变得简单化。
面向对象的编程思想简称:OOP(Object Oriented Programming)
面向对象的三大特征
封装: 把相关的数据封装成一个“类”组件 (用private修饰后的成员变量或者成员方法)
继承: 是子类自动共享父类属性和方法,这是类之间的一种关系
多态: 增强软件的灵活性和重用性 (使类中加入很多接口)
类和对象
类:
Java语言最基本单位就是类,类似于类型,对事物的抽象模板,可以理解为模板或者设计图纸
对象:
每个对象具有三个特点:对象的状态,对象的行为和对象的标识。
1.对象的状态用来描述对象的基本特征。(类成员属性);
2.对象的行为用来描述对象的功能。(类的方法)
3.对象的标识是指对象在内存中都有一个唯一的地址值用来和其他对象区分开来。
4.类是一类事物的抽象,对象是具体的实现。
类和对象的关系
1.计算机语言来怎么描述现实世界中的事物的? 属性 + 行为
2.那怎么通过java语言来描述呢?
可以通过类来描述一类事物,用成员变量描述事物的属性,用方法描述事物的行为.
对象在内存中的存储
Java把内存分成5大区域,我们重点关注栈和堆
补充:静态区和非静态区
对象的存储方式:
局部变量:存在栈中,方法执行完毕内存就被释放
对象(new):存在堆中,对象不再被使用时,内存才会被释放
创建对象时,内存究竟发生了什么?
Person p = new Person();//短短这行代码发生了很多事情
TIPS: 栈与队列指的是一种数据的结构。
栈:先进后出(FILO – First In Last Out 简称FIFO),对象的引用名和地址存在这里
堆:所有new出来的对象都存在堆里包含内存地址,这里保存的是具体的对象
1.把Person.class文件加载进内存
2.在栈内存中,开辟空间,存放引用变量p,并把p压出栈底
3.在堆内存中,开辟空间,存放Person对象
4.对成员变量进行默认的初始化
5.对成员变量进行显示初始化
6.执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
7.堆内存完成
8.把堆内存的地址值赋值给变量p ,p就是一个引用变量,引用了Person对象的地址值
访问控制符
1.用来控制一个类,或者类中的成员的访问范围
2.访问控制符又称权限控制符,需要记住
TIPS:
1.default是表示不写修饰符,默认,如果写default单词来修饰会报错
2.当创建类时 没有加修饰符class会默认为public
类的结构
类的封装
什么是封装?
为了外部可以按照我们提供的方式(方法)来操作属性
概念:
封装是隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式,比如类和方法
优点:提高安全性、提高重用性
如何封装:
1.使用private关键字修饰类的成员属性或者修饰成员方法
2.对于成员变量:提供对应的get/set方法
3.对于方法:在本类的公共方法中调用此私有方法
匿名对象
使用场景:
当被调用的对象只调用一次时(多次会创建多个对象浪费内存)
new Demo().show();//创建了一个对象调方法
new Demo().game();//又创建了一个对象调方法
构造方法
概念:
1.一种特殊的方法,是一个与类同名且没有返回值类型的方法
2.构造方法的主要功能就是完成对象创建或者初始化
3.当类创建对象(实例化)时,就会自动调用构造方法
4.构造方法与普通方法一样也可以重载.
注意:
当只提供了含参构造,默认的无参构造会被覆盖,所以在创建重载的构造方法时,一定注意手动添加无参构造
构造代码块
形式:
{ 代码… }
构造代码块的特点:
- 位置: 在类的内部,在方法的外部
- 作用: 用于抽取构造方法中的共性代码
- 执行时机: 每次调用构造方法前都会调用构造代码块
- 注意事项: 构造代码块优先于构造方法加载
局部代码块
- 位置:方法内(在方法里面的代码块)
- 作用:控制变量的作用范围(作用范围越小,越好,越安全)
- 执行时间:调用该方法时
1.当通过对象调用方法时,会调用对象的功能,如果方法中有局部代码块,就会去执行此局部代码块的代码
2.调用方法时如果有局部代码块才会去执行局部代码块
3.在花括号定义的变量,出了花括号就会被回收
静态代码块
位置:类里方法外
执行:静态资源随着类的加载而加载,并且只被加载一次,一般用于项目的初始化(即使在new对象也不会在执行)
作用:专门用来完成一些需要在第一时间加载并只加载一次的资源
形式:
static{}
代码块之间的运行顺序
如果有继承父类
第一次运行
- 父类~子类按顺序 执行静态代码块(只会执行一次,并存放在内存中直到程序停止)
- 父类构造代码块~父类构造方法 (创建对象时执行)
- 子类构造代码块~子类构造方法 (创建对象时执行)
- 局部代码块(当调用有静态代码块的方法执行)
总结:静态优先普通,父类优先子类
特殊的参数
public void method(int... i) {
int[] a = i;
}
public void test(){
method(1,2,3,4,5,6,7,8,9);
}
功能:可以传入很多int类型的参数理论个数不限
规定:这种定义时这种参数只可以写在参数的最后一个
调用:实则可变参数类型就是数组,只不过是写法不同
Java类中编辑代码顺序
- 抽取形成类(类.class)
- 属性 – 成员变量 – 属性还可以封装提供get、set方法
- 静态代码块:类加装的时候加装,只加载一次
- 构造代码块:如果构造方法有需要提取的共性内容,可以写构造代码块
- 构造方法:创建对象/赋值,默认存在无参构造,创建对象时立即调用
- 普通方法/成员方法:完成一些业务功能(行为)
- 局部代码块:写在方法中的代码块,作用于控制变量的范围,调用该方法时执行
类方法的重载
作用:是为了方便外界对方法进行调用,什么样的参数程序都可以找到对应的方法来执行,体现的是程序的灵活性
重载对象:在同一个类中的方法和构造方法
重写规则:在同一类中方法名相同,且参数列表不同即构成重载
@Overload
检测方法是否被重载,一般写在方法的上一行
注意
构造方法重写时没有返回类型且方法名与类名相同,但参数列表不同
特性1----封装
概念:
1.封装是隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式,比如类和方法
2.限制外界的访问,按照我们指定的方式才能调用
优点:
- 提高安全性
- 提高重用性
如何封装一个类的?
使用private关键字修饰方法或者成员属性
class Student{
//1.把成员变量私有化
private String name;
//2.提供get set 方法,按照自己的方法要求去修改和获取
// 把私有方法放在公共方法里供外界调用即可
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
特性2----继承
类继承的概念
- 继承是面向对象最显著的一个特征,
- 继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并扩展新的能力.
- Java继承是会用已存在的类的定义作为基础建立新类的技术
- 新类的定义可以增加新的数据或者新的功能,也可以使用父类的功能,但不能选择性的继承父类(超类/基类)(被private修饰过的成员变量或者方法)
- 这种继承使得复用以前的代码非常容易,能够大大的缩短开发的周期,降低开发费用.
继承的特点
- 使用extends关键字来表示继承关系
- 相当于子类把父类的功能复制了一份,但private修饰的是不可见、不可调用的
- java只支持单继承,一个子类只能有一个父类
- 继承可以属性和方法都可传递
- 继承只可使用父类可见的变量或方法(public修饰)
- 继承多用于功能的修改,子类可以在拥有父类功能的同时,进行功能拓展
- 要求子类必须是父类的一种继承结构,依赖性非常强,像是is a(强耦合)的关系
- 子类可以直接调用父类的方法或成员属性,如果子类遇到与父类同名的属性时需要使用super.属性进行使用
特别注意
如果一个类没有明确指定父类,那么默认继承顶级父类Object,所以super()会默认调用Object的无参构造
子类实例化时(new),程序的父类和子类初始化的顺序
实例化子类时首先会找到祖上级别的super类先运行:
1.父类构造代码块
2.父类构造方法
3.子类构造代码块
4.子类构造方法
5.直到运行到调用的子类的构造代码块和构造方法即初始化完成
子类构造方法的特殊性
1.系统默认加入一个父类的无参构造方法
2.如果父类没有无参构造方法,可调用有参构造或重写无参构造方法
3. this和super构造函数时只能选择一种,鱼和熊掌不可兼得
4. 继承的时候把静态资源也赋值过来了,但不让重写,但是子类可以使用父类的静态方法
子类对父类方法的重写
重写的原则:
只允许功能拓展,不允许修改源代码
遵循OCP原则 1.面向修改关闭 2.面向功能拓展开发
重写规则:
1.和父类的方法签名(方法名,返回值类型,参数列表),必须保持一致
2.修改的是子类的功能,父类的功能并没有发生改变
3.子类必须有权限去重写父类的功能,父类的私有属性和方法无法被重写
4.子类的方法修饰符权限>=父类被重写方法的修饰符权限
5.父类构造方法不可以重写,构造方法的名字必须与类名相同
6.子类重写父类的方法,异常范围不能比父类方法更大
重写的意义:
是想在不修改源代码的基础之上,完成业务的拓展
子类构造方法初始化父类构造方法:
1.子类构造方法默认第一行就存在super(),所以在创建子类对象时默认会调用父类无参构造
2.父类没有无参构造时,需要手动添加super(参数列表)。
3.当父类中没有无参构造方法时,必须要调用父类的一个有参构造方法
@Override注解
检查方法是不是重写父类的,位置写在方法的上一行
重载Overload 与重写Override的区别
重载:指在一个类中的现象,是指一个类中有很多同名的方法,但是方法的参数列表不同
重写:发生了继承关系以后(两个类),子类去修改父类原有的功能
重载的意义:是为了方便外界对方法进行调用,什么样的参数程序都可以找到对应的方法来执行,体现的是程序的灵活性
重写的意义:是在不修改源码的前提下,进行功能的修改和拓展
(OCP原则:面向修改关闭,面向拓展开放)
特性3----多态
概念1
1.指同一个实体同时具有多种形式,即同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
2.可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。
怎么就可以构成多态?
前提1:子类继承父类
前提2:有父类方法的重写
父类引用指向子类对象构成多态
多态的好处
- 多态可以让我们不用关心某个对象到底具体是什么类型,就可以使用该对象的某些方法
- 提高了程序的可扩展性和可维护性
- 提供通用的解决方案
多态的出现(意义)就是为了统一调用标准
多态的使用
//成员变量: 使用的是父类的
//成员方法: 由于存在重写现象,所以使用的是子类的
Father a = new Son();
使用多态请注意的事项
当 父类 a = new 子类();
0.编译(保存)看左边,运行(测试)看右边(声明的是父类的对象,但功能使用的是子类的功能)
1.父类无法使用子类的特有功能
2.父类的静态方法是不可以被重写的,那个类调用就返回它的静态方法
3.多态中成员变量使用的是父类的,方法使用的是子类的
4.如果父类a和子类都有相同的成员变量,多态中a的成员变量是父类a的。只有行为是属于子类的!!
概念2
看不懂概念1可以看这个更加通俗,更好理解
Father a = new Son();
1.父类类型Father的引用对象a,保存着子类对象的Son值(父类引用指向子类对象)
2.多态中成员方法使用的是父类的声明,子类的实现
3.同一种事物的多种表现形式,可以把多种子类都当做父类来看,统一标准
4.new出来的对象看成父亲的对象进行使用,行为是子类的但是属性是父类的