一文带你了解java面向对象的三大特性:继承、封装、多态
1.继承
继承是类与类的一种关系,子类拥有父类的所有(public,default,protected)属性和方法,从而实现了代码的复用。**
继承与实现的区别:
- 概念不同
继承:子类与父类的继承。如果多个类的某个部分的功能相同,那么可以抽象出一个类出来,把他们的相同部分都放到父类里,让他们都继承这个类。
实现:接口的实现。如果多个类都有一个行为,但是处理的方法方式不同,那么就定义一个接口,也就是一个标准,让各个类分别实现这个接口,各自实现自己具体的处理方法。
- 关键词不同
继承:extends,实现:implements
- 数量不同
单继承,多实现。
- 属性不同
在接口中只能定义全局常量(public static final ),和空的方法体;而在继承中可以定义属性,方法等…
注*:JDK 1.8 以后,接口里可以有静态方法和方法体了。*
- 限制不同
某个接口被类实现时,在类中一定要实现接口中的抽象方法;而继承则无需。
2.封装
-
为什么需要封装?
我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?
如果我们把洗衣机的内部结构暴露出来,当我们使用的时候可能会误操作,碰到一些核心部件更改了配置,导致洗衣机功能出现问题,不能正常工作,所以封装就显得很有必要,把需要暴露的暴露出来,比如洗衣机的一些按钮和加水的地方,不需要的隐藏起来,比如发动机,内部芯片电线等,这样就保证了洗衣机的稳定工作和安全性。 -
封装性的设计思想:
隐藏
对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。把该隐藏的隐藏起来,该暴露的暴露出来
。 -
封装的程序设计意义:为了实现程序设计的“高内聚,低耦合”。
- 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
- 低耦合 :仅对外暴露少量的方法用于使用。
例如:通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx() 和setXxx()实现对该属性的操作,以实现高内聚与低耦合。
3.多态
Java中的多态主要指引用多态
和方法多态
。
引用多态
:父类引用可以指向本类对象,也可指向子类对象。引用多态的强大主要体现在调用属性、方法时,可以根据引用具体指向的对象去调用,例如:子类中重写
了父类方法。子类重写父类的方法,在调用方法时根据引用指向的子类对象决定调用哪个具体的方法。
方法多态
:方法多态的强大主要体现在可以根据调用时参数的不同,而自主匹配调用的方法,例如:重载
。
方法重写与重载
的区别:
重写
:一般发生在有继承关系的子类中,子类中定义了一个方法,其方法名、返回值类型、参数列表 与父类中某个方法一样,此时就是子类中重写(覆盖)了父类的同名方法。
-
子类重写的方法访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
-
子类方法抛出的异常不能大于父类被重写方法的异常
-
子类不能重写父类中声明为private权限的方法
重载
(Overloading):发生在同一个类中,存在 多个方法的方法名相同,参数列表不同。参数列表不同指的是参数个数、参数类型或者参数的顺序不同。 -
被重载的方法可以声明新的或更广的检查异常;
-
被重载的方法可以改变访问修饰符;
-
被重载的方法返回类型可以不同;
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为
static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
注意:
这里我们讨论多态调用属性和方法的规则:
这里假设两个类Student extends Person ,父类是Person,子类是Student
Person 引用指向子类对象Student,
Person p=new Student()
当p调用属性时:p只能调用Person类的属性,即使Student定义了一模一样的属性,p实际调用的也是Person类的属性
当p调用方法时:
Student 没有重写Person的方法,那么p只能调用Person类里面的方法
Student 重写了 Person的方法,那么p调用被子类重写的方法时,p在编译时是Person的方法,运行时是Student重写的方法。
关于多态这里还要说明一点,关于对象的类型转换:
- 从子类到父类的类型转换可以自动进行; Person p=new Student()
- 从父类到子类的类型转换必须通过
强制类型转换
实现;Student s=(Student)Person; - 无继承关系的引用类型间的转换是非法的
- 在强制类型转换之前可以使用
instanceof
一段代码体会一下:
public static void main(String[] args) {
Object obj = "Hello";//向上转型
String objStr = (String) obj;//向下转型
System.out.println(objStr);
Object objPri = new Integer(5);//向上转型
// 下面代码运行时引发 ClassCastException 异常,
// 因为 objPri 分配的对象不是String而是 new Integer(5)
String str = (String) objPri;//向下转型失败
}
运行结果:
Hello
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at Random_name.sgm.thisandsuper.Student.main(Student.java:64)
因为在对象强制类型转换时,有可能会出现类型转换异常ClassCastException,所以我们在向下转型时需要检查,我们可以使用instanceof进行检查。
x instanceof A :检验x 是否为类A 的对象,返回值为boolean
- 要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
- 如果x属于类A的子类B,x instanceof A值也为true。
//如果检查为true就可以进行向下转型,将父类强制类型转换为子类
//Object为所有类的父类,所以可以引用任何类对象
public static void fun(Object o){
if(o instanceof Object){
Object ob=(Object)o;
System.out.println("Object");
}
if(o instanceof Person){
Person p=(Person)o;
System.out.println("Person");
}
if(o instanceof Student){
Student s=(Student)o;
System.out.println("Student");
}
}
public static void main(String[] args) {
Object o1=new Person();
fun(o1);
System.out.println("-------------");
Object o2=new Student();
fun(o2);
System.out.println("-------------");
Person p=new Student();
fun(p);
}
运行结果:
Object
Person
-------------
Object
Person
Student
-------------
Object
Person
Student
本文地址:https://blog.csdn.net/weixin_43914604/article/details/107690623
上一篇: 本地线程变量:ThreadLocal
下一篇: rocketmq发送有序消息笔记