Java 多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作
多态的优点
- 1. 消除类型之间的耦合关系
- 2. 可替换性
- 3. 可扩充性
- 4. 接口性
- 5. 灵活性
- 6. 简化性
多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
比如:
Parent p = new Child();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
以下是一个多态实例的演示,详细说明请看注释:
Test1.java 文件代码:
public class Test1 {
/*
* 多态:
* 重载:当方法名相同时,根据方法的参数列表不一样,具有不同的方法实现
* 重写:当具有相同父类(接口)时,根据子类所具有的不同方法执行不同的操作
*/
public static void main(String[] args) {
// //重写的多态性
// Animals c=new Cat();
// c.act();
// Animals d=new Dog();
// d.act();
// double e=3.4;
// int f=(int) e;
// //向下造型(强制转型)
// Animals c=new Cat();
// c.act();
// Cat d=(Cat) c;
// d.work();
//
// Animals e=new Dog();
// e.act();
// Dog f=(Dog)e;//向下造型 增肥
// f.work();
//
// Animals g=f;//向上造型 瘦身 Animals g=new Dog();
// g.work();//编译错误,引用c前面的类型没有work方法
show(new Cat());
show(new Dog());
}
private static void show(Animals a) {//Animals a =new Cat(); 向上造型 Animals a=new Dog(); 向上造型
//instanceof
//instanceof前面的引用所指向的对象类型,是否是instanceof后面类型的子类或同类型
if(a instanceof Cat){//判断a所指向的对象类型是否为Cat;
Cat c=(Cat) a;//如果是Cat向下造型为Cat
c.work();
}else if(a instanceof Dog){//判断a所指向的对象类型是否为Dog
Dog d=(Dog) a;//如果是Dog向下造型为Dog
d.work();
}
}
}
abstract class Animals{
abstract void act();
}
class Cat extends Animals{
@Override
void act() {
System.out.println("吃鱼");
}
public void work(){
System.out.println("抓老鼠");
}
}
class Dog extends Animals{
@Override
void act() {
System.out.println("啃骨头");
}
public void work(){
System.out.println("看家");
}
}
/*
* 多态:
* 重载:当方法名相同时,根据方法的参数列表不一样,具有不同的方法实现
* 重写:当具有相同父类(接口)时,根据子类所具有的不同方法执行不同的操作
*/
public static void main(String[] args) {
// //重写的多态性
// Animals c=new Cat();
// c.act();
// Animals d=new Dog();
// d.act();
// double e=3.4;
// int f=(int) e;
// //向下造型(强制转型)
// Animals c=new Cat();
// c.act();
// Cat d=(Cat) c;
// d.work();
//
// Animals e=new Dog();
// e.act();
// Dog f=(Dog)e;//向下造型 增肥
// f.work();
//
// Animals g=f;//向上造型 瘦身 Animals g=new Dog();
// g.work();//编译错误,引用c前面的类型没有work方法
show(new Cat());
show(new Dog());
}
private static void show(Animals a) {//Animals a =new Cat(); 向上造型 Animals a=new Dog(); 向上造型
//instanceof
//instanceof前面的引用所指向的对象类型,是否是instanceof后面类型的子类或同类型
if(a instanceof Cat){//判断a所指向的对象类型是否为Cat;
Cat c=(Cat) a;//如果是Cat向下造型为Cat
c.work();
}else if(a instanceof Dog){//判断a所指向的对象类型是否为Dog
Dog d=(Dog) a;//如果是Dog向下造型为Dog
d.work();
}
}
}
abstract class Animals{
abstract void act();
}
class Cat extends Animals{
@Override
void act() {
System.out.println("吃鱼");
}
public void work(){
System.out.println("抓老鼠");
}
}
class Dog extends Animals{
@Override
void act() {
System.out.println("啃骨头");
}
public void work(){
System.out.println("看家");
}
}
instanceof关键字
Test2.java 文件代码:
public class Test2 {
public static void main(String[] args) {
Person e=new Emp();
//instanceof前面的引用所指向的对象类型,是否是instanceof后面类型的子类或同类型
System.out.println(e instanceof Person);//true
System.out.println(e instanceof Emp);//true
System.out.println(e instanceof Boss);//false
Person p=new Person();
System.out.println(p instanceof Emp);//false
}
}
class Person{
}
class Emp extends Person{
}
class Boss extends Person{
}
public static void main(String[] args) {
Person e=new Emp();
//instanceof前面的引用所指向的对象类型,是否是instanceof后面类型的子类或同类型
System.out.println(e instanceof Person);//true
System.out.println(e instanceof Emp);//true
System.out.println(e instanceof Boss);//false
Person p=new Person();
System.out.println(p instanceof Emp);//false
}
}
class Person{
}
class Emp extends Person{
}
class Boss extends Person{
}
内部类
Test3.java 文件代码:
public class Test3 {
//内部类 一个类可以定义另一个类的内部,定义在类内部的类称为内部类,定义在外面的称为外部类
public static void main(String[] args) {
Outer o=new Outer(100);
o.print();
//除了在外部类的构造方法里创建内部类的对象,还可以通过下面方式创建对象
Outer.Inner i=new Outer(100).new Inner();
i.timeInfo();
}
}
class Outer{
private int time;
private Inner inner;
Outer(int time){//int time=100;
this.time=time;
inner=new Inner();//一般在外部类的构造方法里创建内部类的对象
inner.timeInfo();//通过内部类对象调用内部类的方法
}
private void go(){
System.out.println("跑步");
}
public void print(){
System.out.println(time);
}
class Inner{
public void timeInfo(){
go();//内部类可以调用外部类的方法(包括私有的)
time++;//内部类可以调用外部类的属性(包括私有的) time=time+1;
}
}
}
//内部类 一个类可以定义另一个类的内部,定义在类内部的类称为内部类,定义在外面的称为外部类
public static void main(String[] args) {
Outer o=new Outer(100);
o.print();
//除了在外部类的构造方法里创建内部类的对象,还可以通过下面方式创建对象
Outer.Inner i=new Outer(100).new Inner();
i.timeInfo();
}
}
class Outer{
private int time;
private Inner inner;
Outer(int time){//int time=100;
this.time=time;
inner=new Inner();//一般在外部类的构造方法里创建内部类的对象
inner.timeInfo();//通过内部类对象调用内部类的方法
}
private void go(){
System.out.println("跑步");
}
public void print(){
System.out.println(time);
}
class Inner{
public void timeInfo(){
go();//内部类可以调用外部类的方法(包括私有的)
time++;//内部类可以调用外部类的属性(包括私有的) time=time+1;
}
}
}
匿名内部类
Test4.java 文件代码:
public class Test4 {
//匿名内部类 匿名内部类也就是没有名字的内部类
/*
* 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
*/
public static void main(String[] args) {
Persons c=new Child();
c.eat();
System.out.println("c="+c);
//匿名内部类
//抽象类不能实例化,如果硬要实例化,只能创建抽象类的匿名内部类
Persons p=new Persons(){
@Override
public void eat() {
System.out.println("不知道名字的类,应该要去吃饭");
}
};
p.eat();
System.out.println("p="+p);
//接口不能实例化,如果硬要实例化,只能创建接口的匿名内部类
A a=new A() {
public void a() {
System.out.println("a");
}
};
a.a();
}
}
abstract class Persons{
public abstract void eat();
}
class Child extends Persons{
@Override
public void eat() {
System.out.println("孩子!吃饭了");
}
}
interface A{
public void a();
}
//匿名内部类 匿名内部类也就是没有名字的内部类
/*
* 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
*/
public static void main(String[] args) {
Persons c=new Child();
c.eat();
System.out.println("c="+c);
//匿名内部类
//抽象类不能实例化,如果硬要实例化,只能创建抽象类的匿名内部类
Persons p=new Persons(){
@Override
public void eat() {
System.out.println("不知道名字的类,应该要去吃饭");
}
};
p.eat();
System.out.println("p="+p);
//接口不能实例化,如果硬要实例化,只能创建接口的匿名内部类
A a=new A() {
public void a() {
System.out.println("a");
}
};
a.a();
}
}
abstract class Persons{
public abstract void eat();
}
class Child extends Persons{
@Override
public void eat() {
System.out.println("孩子!吃饭了");
}
}
interface A{
public void a();
}