Polymorphism[JAVA]

1.多态性

1.0个人理解

  • 面向对象多态这个点其实是比较难理解的,但是结合封装和继承的角度去看的话,其实不难,多态性只是概念上比较难懂,更多时候是需要去多写代码去理解它的性质。
  • 多态的前提是要有继承和重写的,举个例子来说吧,
  • 每一个动物都会叫,但是每种动物的叫声可能就不一样了,这个时候我们定义一个动物类写一个叫声方法,
  • 然后猪类、猫类、狗类这些类继承了动物类就获得了(重写)动物类的叫声方法,
  • 我们在这个方法里定义每种动物自己特定的叫声(方法体),当调用的时候有动物类的引用就可以,然后造猪类、猫类、狗类的对象就行了(父类引用指向子类对象)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class animals {
public void voice(){
System.out.println("动物都可以叫");
}
}
class dog extends animals{
@Override
public void voice() {
System.out.println("汪汪汪");
}
}
class cat extends animals{
@Override
public void voice() {
System.out.println("喵喵喵");
}
}
class text{
public static void main(String[] args) {

//1多态的体现(直接调用)
animals a = new dog();
a.voice();
animals a1 = new cat();
a1.voice();

//2多态的体现(传参方式)
text t = new text();
t.method(new dog());
t.method(new cat());
}

public void method(animals als){
als.voice();
}
}

1.1多态核心

简单来说就是事物存在的多种形态

多态前提:要有继承关系,要有方法重写,要有父类引用指向子类对象

父类引用指向子类对象:

1
Father father = new Son();

1.2多态弊利

利处
提高了代码的维护性(继承保证)

提高了代码的扩展性(由多态保证)

弊端
不能使用子类的特有属性和方法

关键字instanceof 判断前面的引用是否是后面的数据类型

1.3成员访问特点

  • 成员变量
    编译看左边(父类),运行看左边(父类)

  • 成员方法
    编译看左边(父类),运行看右边(子类){动态绑定}

  • 静态方法
    编译看左边(父类),运行看左边(父类)
    静态和类相关,算不上重写,所以,访问还是左边的
    只有非静态的成员方法,编译看左边,运行看右边

  • CODE

1
2
3
4
5
6
7
//编译左,运行右
ainmals als = new cat(); //父类引用指向子类对象
als.eat();

//遍历和运行都是左
System.out.println(als.leg);

1.4虚拟方法调用

虚拟方法调用(多态情况下)

  1. 调用子父类同名同参的方法时,在多态的情况下,父类的方法就称为虚拟方法
  2. 父类根据赋给它不同的子类,动态调用属于子类自己的该方法
  3. 这样的方法在编译期间,是无法确定的

动态绑定

ainmals als = new cat();//父类引用指向子类对象
als.eat();

编译时为父类类型,但是方法调用是在运行才知道
所以调用的子类的方法

1.5上下转型

向上转型(就是多态)
向上转型(父类引用指向子类对象)
父类名称 父类变量名=new 子类名称();
Person p=new superman();

向下转型 (需用instanceof判断)
强制类型转换
子类名称 子类变量名 = (子类名称)父类变量名
superman s=(superman)p;

2.instanceof关键词

2.1instanceof用法

常用于多态向下转型时
为避免出现classcast异常,向下转型前先使用它进行判断
判断格式

1
If(a instanceof A)

判断对象a是否是类A的实例
是返回true 不是返回false

如此格式返回true如下格式也返回true

1
If(b instanceof B)

2.2代码体现

1
2
3
4
5
6
7
8
9
10
11
Watch watch = new TraditionWatch(); 	//父类引用指向子类对象
watch.seeTime();
watch.collect();
if (watch instanceof TraditionWatch){ //判断watch是不是TraditionWatch的实例
TraditionWatch tdw =(TraditionWatch) watch;
tdw.crafts(); //子类调用自己特有的方法
}
if (watch instanceof SmartWatch){
SmartWatch swh = (SmartWatch) watch;
swh.fashion();
}

3.面试题

3.1如下代码输出?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class InterviewTest {

public static void main(String[] args) {
faze fe = new zil();
fe.add(10,2,3,4,2,2,1); //结果:zil

if (fe instanceof zil) {
zil z = (zil) fe;
z.add(1, 2, 3); //结果:zil222
}
}
}

//构成方法的重写 可变形参讲过这个问题 ...和[]是一个意思

class faze{

public void add(int a,int ... arr){
System.out.println("faze");
}
}

class zil extends faze{

@Override
public void add(int a, int[] arr) {
System.out.println("zil");
}

//对于本类来说构成重载 对于父类来说不构成重写
public void add(int a, int b,int c) {
System.out.println("zil222");
}
}

4.抽象(abstract)

4.1理解抽象

  1. 抽象可以理解为关键词,也可以理解为面向对象的一种性质
  2. 抽象可以修饰类和方法,抽象方法没有方法体
  3. 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者接口
  4. 抽象类不能实例化,要实例化只能通过子类(抽象多态)
  5. 抽象类子类要么是抽象类,要么实现所有所有父类的抽象方法
1
2
3
abstract class CLASS_NAME{
public abstract void METHOD_NAME( );
}

4.2关键词冲突

static

  • 被abstract修饰的方法没有方法体
  • 被static修饰的方法可以用类名调用,抽象方法没有方法体没意义

final

  • final修饰的方法体不能被重写,abstract则是子类必须重写

private

  • 被abstract修饰是为了让子类看到并强制重写
  • 被private修饰不让子类访问,所以两者也是矛盾的

4.3匿名抽象

对象不匿名,类匿名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void anonymousUs(){
//匿名类的使用
aHuman aa = new aHuman() {
@Override
public void eat() {
System.out.println("建筑工人多吃肉有力气干活");
}

@Override
public void learn() {
System.out.println("建筑工人学习土木知识");
}
};
anony(aa);

对象,类都匿名

1
2
3
4
5
6
7
8
9
10
11
anony(new aHuman() {
@Override
public void eat() {
System.out.println("电器工人多吃肉有力气干活");
}

@Override
public void learn() {
System.out.println("电器工人学习CAD和工业知识");
}
});

5.接口(Interface)

5.1理解接口

  1. 从狭窄的角度来讲就是指Java中的interface
  2. 从广义的角度来讲就是对外提供规则的都是接口
  3. 接口就是一种规范(开发中会体现面向接口编程)
  4. 极大意义上弥补Java的单继承性
  5. 接口的使用充分的体现了多态性

5.2接口特点

  1. 接口中没有构造器(无法实例化)
  2. 接口实例化通过实现类来实例化(多态体现)
  3. 接口中的方法都是抽象的(JDK1.8前)
  4. 实现接口的类,如果没有实现全部接口的方法,必须加上abstract
  5. 如果此类实现了接口的所有方法,就没必要加上abstract

5.3JDK8新特征

成员特点

变量:只能是常量,并且是static和public的
方法:只能是抽象方法(1.8以后还可以定义静态方法,default方法)
注:静态方法和default方法有方法体,抽象方法没有方法体

注意事项

  1. 接口中的静态方法只能通过接口.方法名调用
  2. 接口中的default方法类可以实现,也可以不实现
  3. 当实例类继承的两个接口中出现同名的方法后,需要通过接口名.super.方法名调用
  4. 若上述两个接口的参数也一样的情况下会报错(接口冲突)
  5. 实际开发中不会这么无聊的去写
1
2
3
4
5
6
7
8
9
interface See{
public static final MAX_NUM = 996;

public abstract void methdo1();

public default void method2(){};

public static void method3(){};
}

5.4匿名接口

  1. 非匿名实现类的匿名对象(多态写法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    Computer.transferData(new Flash());
````

2. 接口匿名 类非匿名

```java
USB mp3 = new USB() {
@Override
public void start() {
System.out.println("mp3工作");
}

@Override
public void stop() {
System.out.println("mp3停止工作");
}
};
  1. 接口匿名 类也匿名
1
2
3
4
5
6
7
8
9
10
11
Computer.transferData(new USB() {
@Override
public void start() {
System.out.println("游戏机工作");
}

@Override
public void stop() {
System.out.println("游戏机停止工作");
}
});

6.两者区别

  1. 抽象类中定义的是该继承体系的共性功能,被继承体现的是”is a”的关系
  2. 接口中定义的是该继承体系的拓展功能,被实现体现的是”like a”的关系
  3. 其实接口也在逐渐的类化,例如JDK8加入了静态方法和默认方法
  4. JDK11又加入了私有方法,基本上实在向抽象类的意义靠拢拉近的

内部定义要求

Abstract:变量/常量谐可 抽象/非抽象方法谐可 有构造方法
Interface:常量 只能抽象方法 没有构造方法

关系区别

类与类:继承、单继承
类与接口:实现、单实现、多实现
接口与接口:继承、单继承、多继承

7.代码块

7.1非静态代码块

随着对象的创建而创建,每创建一个对象执行一次

可在创建对象时,对对象属性进行初始化

1
2
3
{
里面写代码
}

7.2静态代码块

随着类的加载就执行,并且只执行一次

用于初始化类的信息,优先于主方法执行,一般用于加载驱动

注:内部书写要求依据static使用来写

1
2
3
static{
里面写代码
}

7.3题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
看代码想结果
class mst {
static{
System.out.println("static code area");//静态代码块优先于主方法执行
}

public static void main(String[] args) {
System.out.println("我是main方法");
studentss s1=new studentss();
studentss s2=new studentss();
}
}
class studentss{
static{
System.out.println("Students 静态代码块");
}

{
System.out.println("Students 构造代码块");
}

public studentss(){
System.out.println("Students 构造方法");
}
}
1
2
3
4
5
6
7
8
运行结果
static code area
我是main方法
Students 静态代码块
Students 构造代码块
Students 构造方法
Students 构造代码块
Students 构造方法

Polymorphism[JAVA]
http://example.com/2022/04/08/Java初级部分/OOP/Polymorphism/
Author
John Doe
Posted on
April 8, 2022
Licensed under