Java面向对象高级-面向对象思想三大特征:封装、继承、多态
一、封装
我们日常使用的电脑主机,把cpu、内存、主板等都封装到机箱里面去。假如没有机箱的话就会导致主机、主板等全部都散落在一处,然后开机没有开机按钮,那么需要我们直接操作接跳线才能把电脑开启,这样的话假如操作不慎的话,会让机器损坏
危险
。
如果用机箱封装起来的话,那么就不需要这样做了,体现了封装的安全性
。
你拿电脑去加内存条,可以直接给电脑维修的人,等他加好内存之后,你拿到的还是那个机箱,里面发生了怎样的变化你不知道,封装的第二好处就是
变化隔离
在机箱里面提供一个开机按钮,就不需要你直接使用跳线来开机,体现了封装的-
便于使用
的特性。
只要机箱提供了一个开机的功能,然后无论这个机箱拿到哪里去,都可以使用这个开机的功能,体现了封装的-
重复性
的特性。
1、不使用封装
创建一个Employee类,定义姓名、工号、性别的成员变量,和工作的方法,成员使用public进行修饰
创建Employee对象,并对成员进行赋值,最后调用对象中工作的方法
代码案例
package cn.com.example6;
public class Employee {
public int id;
public String name;
public String sex;
public void handlerWork(){
System.out.println("name:"+name+",id:"+id+",sex:"+sex);
}
public static void main(String[] args) {
Employee employee = new Employee();
employee.id = 1001;
employee.name = "admin";
employee.sex = "不是人";
employee.handlerWork();
}
}
如果不使用封装,很容易赋值错误,并且任何人都可以更改,造成信息的不安全
解决:使用封装
2、封装的实现
类中的属性访问修饰符为
private
,不能使用对象名.属性名的方式直接访问对象的属性。
public访问修饰符,公共的,谁都可以访问
private访问修饰符,私有的,只有自己可以访问【在自己的类中可以访问,在类外部不能访问】
如果想让外部类访问,那么我们可以提供一些方式供外部访问【get获取、set设置】【从直接访问更改为间接访问,从被动更改为主动】
代码案例
package cn.com.example6;
public class Employee {
private int id;
private String name;
private String sex;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void handlerWork(){
System.out.println("name:"+name+",id:"+id+",sex:"+sex);
}
public static void main(String[] args) {
Employee employee = new Employee();
employee.id = 1001;
employee.name = "admin";
employee.sex = "不是人";
employee.handlerWork();
}
}
3、封装的好处
- 隐藏了类的具体实现
- 操作简单
- 提高了对象数据的安全性
二、继承
继承:用于描述类和类之间的关系
比如:儿子类和父亲类,没有明显的描述出两个类之间的关系,所以不能直接说两个类有继承的关系
代码案例
package cn.com.example6;
public class Father {
public String name;
public int age;
public void handlerMessage(){
System.out.println("我是父亲");
}
}
class Son{
public String name;
public int age;
public void handlerMessage(){
System.out.println("我是儿子");
}
}
1、继承的特点
- 描述类和类之间的关系
- 降低类和类之间的重复代码【代码不会冗余】
2、extends关键字
extends:用于描述类与类之间的关系【继承】
语法:
public class 子类类名 extends 父类类名{
}
代码案例
package cn.com.example6;
public class Father {
public String name;
public int age;
public void handlerMessage(){
System.out.println("我是父亲");
}
public static void main(String[] args) {
// 实例化子类对象
Son son = new Son();
// 调用继承的方法handlerMessage
son.handlerMessage();
}
}
// 子类继承了父类
class Son extends Father{
public String name;
public int age;
public void handlerMethod(){
System.out.println("子类的独有方法");
}
}
注意事项:
1、类名的设定,被继承的类称之为父类,继承的类称之为子类
2、如果一个类没有显式的继承某个类,那么该类的父类是Object【基类、超类,所有类的父类】
3、子类一旦继承了父类,那么子类就继承了父类中所有非私有属性和方法,不能继承构造器 ,并且子类可以拥有独有的属性和方法
4、不要为了使用或简化某个功能而继承,java中只支持单继承
5、一个父类可以用多个子类,一个子类只能有一个父类【单继承】
3、super关键字
super:类似于this,用于指向子类对象中父类对象
语法:
super.属性名 // 父类属性【继承过来的】
super() // 调用父类构造器【无参、有参】
问题解决:
- 子类对象为什么可以访问父类的成员
- this.y = y+x;有一个隐式的super super.x
- super关键字作用
- 主要存在于子类方法中,用于指向子类对象中父类对象
- 访问父类的属性、函数、构造函数
- 执行子类构造器之前会先执行父类构造器:super()
- super定义
- 如果没有显式的定义,那么系统会自动定义
注意:super()不能和this()一起使用,因为super()需要定义在第一行
代码案例
package cn.com.example6;
public class Father {
public String name;
public int age;
public void handlerMessage(){
System.out.println("我是父亲");
}
public static void main(String[] args) {
// 实例化子类对象
Son son = new Son();
// 调用继承的方法handlerMessage
son.handlerMessage();
}
}
// 子类继承了父类
class Son extends Father{
public String name;
public int age;
// 子类构造器
public Son(){
super(); // 调用无参构造器
}
public void handlerMethod(){
System.out.println("子类的独有方法");
}
}
4、继承内存剖析
通过以上内存图能看出,加载父类的属性和方法比子类的属性和方法提前加载进内存中,那么我们可以在实例化子类对象时直接对属性进行初始化
代码案例
package cn.com.example6;
public class Father {
public String name;
public int age;
public Father() {
}
public Father(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
// 实例化子类对象
Son son = new Son("admin",22);
}
}
// 子类继承了父类
class Son extends Father{
// 赋值
public Son(String name,int age){
super(name,age);
}
}
5、重写
假如子类继承过来的方法内部的功能不满足现有的需求,那么子类可以重新定义该方法,这种做法称之为重写。
重写(Override):方法名相同,参数类型或个数也相同,方法体不同
- 重载和重写的区别
- 重载(Overload)
- 规范:方法名相同,参数类型和参数个数不同
- 定义位置:在本类中
- 重写(Override)
- 规范:方法名相同,参数类型和参数个数也相同,方法体不同
- 定义位置:在子类中
- 重载(Overload)
代码案例
package cn.com.example6;
public class Father1 {
public void handlerMessage(){
System.out.println("这是父类的方法");
}
}
package cn.com.example6;
public class Son1 extends Father1{
@Override
public void handlerMessage() {
System.out.println("这是子类的方法");
}
public static void main(String[] args) {
Son1 son1 = new Son1();
son1.handlerMessage(); // 这是子类的方法
}
}
当方法被重写,子类调用的是重写后的,因为当继承过来的属性和方法在子类中被重新定义,那么继承过来的属性和方法将被隐藏,通过super关键字可调用。
三、instanceof关键字
instanceof关键字:属于比较运算符,用于判断一个对象是否是指定类的对象
代码案例
Person per = new Person();
System.out.println(per instanceof Person); // true
四、抽象类
当描述一个类的时候,如果不能确定功能方法如何定义,那么该功能方法就可以定义为抽象方法,一个类中只要有抽象方法,该类必须是抽象类
1、抽象类的特点
- 有抽象方法的类,该类一定是抽象类
- 抽象类不一定要有抽象方法
- 抽象类不能使用new创建对象
- 抽象方法没有方法体
- 抽象类主要为了提高代码的复用性,让子类继承来使用【重写】
- 编译器会强制子类实现抽象类的未实现的方法,也可以不实现,前提是子类中也要声明为抽象的
2、抽象的优点
- 提高代码复用性,强制子类实现父类中没有实现的功能
- 提高代码扩展性,便于后期的代码维护
3、抽象类不能创建对象,那么抽象类中是否有构造方法?
抽象类中一定有构造方法,主要为了初始化抽象类中的属性,通常由子类实现。
4、final和abstract是否可以同时修饰一个类?
一定不能同时修饰,抽象类中的抽象方法需要被子类重写,而final修饰的类不能被继承,以及final修饰的方法不能被重写
5、抽象类和普通类的区别
抽象类比普通类多了抽象方法以及不能实例化对象,其余的都一样
代码案例
package cn.com.example6;
// 抽象类
public abstract class AbstractFather {
public String name;
// 抽象方法
public abstract void handlerMethod();
}
class Son2 extends AbstractFather{
@Override
public void handlerMethod() {
}
}
五、接口
接口(interface):USB接口,主要用来拓展笔记本的功能,那么在java中的接口主要用来拓展类的功能,可以弥补java单继承的缺点,并且达到了解耦
1、接口概述
代码案例
// 铅笔类
public class Pencil {
}
// 橡皮接口
public interface Rubber {
// 接口中只能定义常量
public String name = "橡皮";
// 接口中只能定义抽象方法
public void handlerMessage();
}
// 带橡皮的铅笔继承了铅笔类实现了橡皮接口
public class PencilWithRubber extends Pencil implements Rubber{
}
2、接口默认修饰符
使用javap进行反编译,发现接口中的属性,默认修饰符:public static final,方法默认修饰符:public abstract
3、接口的特点
- 类实现接口可以通过implements实现,实现接口的时候必须把接口中的所有方法实现
- 一个类可以实现多个接口【多实现】
- 接口中定义的所有属性默认是public static final修饰,即静态常量,所以定义时必须赋值
- 接口中定义的方法不能有方法体,因为接口中定义的方法默认添加了public abstract
- 由于接口中的方法都是抽象,所以不能被实例化
- 对于接口而言,可以使用子类来实现接口中未被实现的功能方法
- 如果实现类中要访问接口中的成员,不能通过super关键字,因为两者没有显示的继承,可以使用接口名直接访问
- 接口没有构造方法
4、接口与类之间的关系
类与类之间的关系是继承,那么接口与类之间的关系是实现,非抽象类实现接口时,必须把接口中所有的方法都实现,类实现接口用implements关键字,类与接口之间是可以多实现【一个类可以实现多个接口】
5、接口与接口之间的关系
接口与接口之间的关系是继承,接口可以继承多个接口【多继承】
比如:在现实生活中,有部分同学在学校期间只会学习,但是有部分同学除了学习还会赚钱
在java中类之间是单继承
在java中是多继承【接口之间】
在java中是多实现【类与接口】
六、多态
多态:多种形态
比如:老师 => 员工=> 儿子
1、多态的好处
父类可以调用不同子类的函数,提高了代码的维护性和扩展性
2、多态的前提条件
- 必须是继承管理
- 子类必须重写
- 向上转型
- 子类对象向上转型给父类类型【核心】
语法:
父类类型 对象名 = new 子类构造器();
代码案例
package cn.com.example6;
public interface InterfaceFather {
public void handlerEat();
public static void main(String[] args) {
// 实例化子类对象并且向上转型为父类引用
InterfaceFather interfaceFather = new ClassSon();
// 调用方法
interfaceFather.handlerEat();
}
}
class ClassSon implements InterfaceFather{
@Override
public void handlerEat() {
System.out.println("这是儿子吃的程序");
}
}
注意:
1、子类一旦向上转型为父类引用,那么父类引用只能调用父类所具备的属性和方法,子类独有的不允许调用
2、当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量
3、当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类重写后的成员方法