多态

多态的概念

  • 多态性,是面向对象中最重要的概念,在java中的体现,对象的多态性:父类的引用指向子类的对象(向上转型),是可以直接应用抽象类和接口中上
  • Java引用变量有两个类型:编译时类型和运行时类型。编译时类型声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边

向上转型

  • 子类可看作是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型
  • 子类到父类的转换通常称作向上转型,通俗来说就是:定义父类对象指向子类对象(多态)(创建对象)(编译看左),然后实例(小类转型为大类)
  • (既可以用父类派生的方法,也可以用子类重写的方法,但是不能使用子类特有的属性和方法)
  • 注意:父类中的静态方法无法被子类重写,所以向上转型之后,只能调用父类原有的静态方法,如果一定要使用子类中的静态方法,只能使用向下转型的方法调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {
public static void main(String[] args) {

Animal animal = new Animal();//普通的创建对象 animal
Animal one = new Animal();//1
//向上转型,隐式转型,自动转型
Animal two = new Cat();//2父类对象two,指向Cat方法,然后调用Cat中的方法
Animal three = new Dog();//3

one.eat();
two.eat();
three.eat();
}
}

向下转型

  • 父类到子类的转换通常被称为向下转型,将子类对象指向父类对象(创建对象)注意:必须进行强制类型转换
  • 转型时转的类型必须是父类对象所指的真实子类对象(向上转型创建的对象),不是任意的强制类型转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test {
public static void main(String[] args) {


Animal one = new Animal();//1
//向上转型,这里的one,two,three都是父类对象
Animal two = new Cat();//2
Animal three = new Dog();//3

/**
* 向下转型、强制类型转换
*将子类的引用指向父类,此处必须进行强转,可以调用子类特有的方法
* */
Cat temp = (Cat)two;
temp.run();
temp.eat();
Dog temp2 = (Dog) two;//报错,two指向的是Cat子类
temp2.eat();
}
}

Instanceof运算符

简介:

  • instanceof是java中二元运算符,左边是对象,右边是类;
  • 当对象是右边类或子类所创建对象时,返回true;否则,返回false
  • instanceof左边显示声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于同一个继承树,否则会编译失败
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
public class Test {
public static void main(String[] args) {

Animal animal = new Animal();
Animal one = new Animal();//1
//向上转型,隐式转型,自动转型
Animal two = new Cat();//2Cat类创建的对象two,转换为特殊的父类
Animal three = new Dog();//3

if (two instanceof Cat){//条件为真,返回值为true执行if语句
Cat temp = (Cat)two;
temp.run();
temp.eat();
Dog temp2 = (Dog) three;
temp2.eat();
System.out.println("two可以转换为Cat类型");
}

if(two instanceof Animal){
System.out.println("Animal");
}
if (two instanceof Object){
System.out.println("Object");
}

//全部都是true,都是可以执行的

抽象类

作用

  • Java中使用抽象类,限制实例化
  • 抽象类:不允许实例化,可以通过向上转型,指向子类实例,完成对象实例
  • 抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。如果没有重写全部的抽象方法,仍然为抽象类
  • 应用场景:某个父类只知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法

抽象方法

  • 必须定义抽象类,抽象方法是不允许包含方法体;在子类中必须重写抽象方法,并提供方法体,否则子类也为抽象类(开摆)
  • abstract定义抽象方法,不需要具体实现
  • 包含抽象方法的类一定是抽象类,但是抽象类中不一定有抽象方法
  • 当抽象方法被定义的时候,子类一定要重写方法,不然的话就定义该子类为抽象类
  • 抽象方法是不可以与static,final,private并存

接口API

概述:

  • 有时必须从几个类中派生出一个子类,继承他们所有的属性和方法,但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果
  • 接口的本质是契约,标准,规范,就像我们的法律一样。指定好后大家都要遵守

作用:

  • 接口定义了某一批类所需要遵守的规范
  • 接口不关心这些类的内部数据,也不关心这些类里的方法的实现细节,他只规定这些类里必须提供某些方法

特点:

  • 接口就是抽象方法和常量值定义的集合
  • 用interface来定义
  • 接口中的所有成员变量都默认是由public static final修饰的
  • 接口中所有抽象方法都是默认是由public abstract修饰的
  • 接口中是没有构造方法
  • 接口中采用多继承机制
  • 其他类调用接口的时候必须重写接口中的所写方法,因为接口是抽象方法与常量值的集合
  • 举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//接口
package com.java.tel;
/**
* 接口访问修饰符:public 默认
*
* */
public interface INet {
/**
*接口当中抽象方法可以不写abstract关键字,访问修饰符默认public
* 当类实现接口时,需要去实现接口中所有的抽象方法,否则需要将该类设置为抽象类
* */

public abstract void network();
void connection();
//接口中可以包含常量,默认public static final
public static final int TEP=20;//常量是不可以改变的,子类调用常量时是不可改变的
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//类调用接口
package com.java.tel;

public class SmartPhone implements INet {
public static final int TEP=30;
public void call(){
System.out.println("智能手表可以打电话");
}
public void network(){
System.out.println("智能手表可以打电话");
}
public void connection(){//重写INet中的connection方法,这里是调用了IPhoto中的默认方法connection
System.out.println("我是重写后的connection方法");
INet.super.connection();//调用接口中的默认方法,这样就不用重写默认方法中的方法体

}

}
1
2
3
4
5
//测试类
INet net = new Smartphone();//声明接口对象net,实例化对象,也就是创建并引用接口对象
System.out.println(INet.TEP);//接口名调用常量
INet net = new SmartPhone();
System.out.println(net.TEP);//创建接口实例化对象,调用常量

接口中的默认方法

作用:

  • 默认方法,当其他类调用接口的时候,可以依据要求是否要重写此方法
1
2
3
4
5
//接口中的默认方法
default void connection (){
System.out.println("我是接口中的默认连接");
}
//default:默认方法,结构中是可以带有方法体,既然不是抽象方法,后面的类可以不重写此方法
1
2
3
4
//测试类中调用接口中的默认方法
INet net = new SmartPhone();//声明接口对象net,实例化对象
net.connection();//

接口中的静态方法

1
2
3
4
5
6
//接口中的静态方法
//接口中的静态方法也是可以带有方法体的
static void stop(){
System.out.println("我是接口中的静态方法");
}
}
1
2
3
4
5
6
//类中调用接口
public void connection(){//重写INet中的connection方法,这里是调用了IPhoto中的默认方法connection,可以不重写
System.out.println("我是重写后的connection方法");
INet.super.connection();//调用接口中的默认方法,这样就不用重写默认方法中的方法体

}
1
2
//测试类中调用静态方法
INet.stop();//接口名.静态方法,调用接口中的静态方法

类调用多接口

用法:,后面跟着多个接口名

1
2
public class FourPhone extends ThreePhone implements IPhoto,INet{}
//子类 extends 父类 implements 接口,接口
关于多接口中重名默认方法处理的解决方案:
  • 当类中调用两个接口时,两个接口中有同名的方法,这时只有重写此方法才能解决报错
  • 子类 extends 父类 implements 接口,接口;当父类与接口中有同名方法时,会默认使用父类中的同名方法
  • 如果父类,与接口中有同名的常量或变量的话,那依然还是无法识别的,只有在子类中定义的同名常量,才不会报错

接口中的继承

作用

  • 接口也可以实现继承,并且可以继承多个父接口,测试类调用接口的时候也需要依据要求重写接口中的方法
  • 如果继承多个父接口中有同名方法,在子类中重写方法解决报错
1
2
3
4
5
package com.java.tel;

public interface ISon extends IFather,IFather2{
void run();
}