Java多态和实现接口的类的对象赋值给接口引用的方法(推荐)

 更新时间:2017年02月21日 09:46:02   投稿:jingxian  
下面小编就为大家带来一篇Java多态和实现接口的类的对象赋值给接口引用的方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

接口的灵活性就在于“规定一个类必须做什么,而不管你如何做”。

我们可以定义一个接口类型的引用变量来引用实现接口的类的实例,当这个引用调用方法时,它会根据实际引用的类的实例来判断具体调用哪个方法,这和上述的超类对象引用访问子类对象的机制相似。

//定义接口InterA
interface InterA
{
 void fun();
}
//实现接口InterA的类B
class B implements InterA
{
 public void fun()
 {
  System.out.println(“This is B”);
 }
}

//实现接口InterA的类C
class C implements InterA
{
 public void fun()
 {
  System.out.println(“This is C”);
 }
}

class Test
{
 public static void main(String[] args)
 {
  InterA a;
  a= new B();
  a.fun();
  a = new C();
  a.fun();
 }
}

输出结果为:

This is B
This is C

上例中类B和类C是实现接口InterA的两个类,分别实现了接口的方法fun(),通过将类B和类C的实例赋给接口引用a,实现了方法在运行时的动态绑定,充分利用了“一个接口,多个方法”,展示了Java的动态多态性。

需要注意的一点是:Java在利用接口变量调用其实现类的对象的方法时,该方法必须已经在接口中被声明,而且在接口的实现类中该实现方法的类型和参数必须与接口中所定义的精确匹配。

--------------------------------------------------------------------------------

扩展

Java运行时多态性:继承和接口的实现

Java是面向对象的语言,而运行时多态性是面向对象程序设计代码重用的一个最强大机制,动态性的概念也可以被说成“一个接口,多个方法”。Java实现运行时多态性的基础是动态方法调度,它是一种在运行时而不是在编译期调用重载方法的机制,下面就继承和接口实现两方面谈谈java运行时多态性的实现。

一、通过继承中超类对象引用变量引用子类对象来实现

举例说明:

//定义超类superA 
class superA {
  int i = 100;

  void fun() {
    System.out.println(“This is superA”);
  }
}

//定义superA的子类subB 
class subB extends superA {
  int m = 1;

  void fun() {
    System.out.println(“This is subB”);
  }
}

//定义superA的子类subC 
class subC extends superA {
  int n = 1;

  void fun() {
    System.out.println(“This is subC”);
  }
}

class Test {
  public static void main(String[] args) {
    superA a;
    subB b = new subB();
    subC c = new subC();
    a = b;
    a.fun();
    (1)
    a = c;
    a.fun();
    (2)
  }
}  

运行结果为:

This is subB

This is subC

上述代码中subB和subC是超类superA的子类,我们在类Test中声明了3个引用变量a, b, c,通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。也许有人会问:“为什么(1)和(2)不输出:This is superA”。java 的这种机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。

所以,不要被上例中(1)和(2)所迷惑,虽然写成a.fun(),但是由于(1)中的a被b赋值,指向了子类subB的一个实例,因而(1)所调用的fun()实际上是子类subB的成员方法fun(),它覆盖了超类superA的成员方法fun();同样(2)调用的是子类subC的成员方法fun()。

另外,如果子类继承的超类是一个抽象类,虽然抽象类不能通过new操作符实例化,但是可以创建抽象类的对象引用指向子类对象,以实现运行时多态性。具体的实现方法同上例。

不过,抽象类的子类必须覆盖实现超类中的所有的抽象方法,否则子类必须被abstract修饰符修饰,当然也就不能被实例化了。

二、通过接口类型变量引用实现接口的类的对象来实现

接口的灵活性就在于“规定一个类必须做什么,而不管你如何做”。我们可以定义一个接口类型的引用变量来引用实现接口的类的实例,当这个引用调用方法时,它会根据实际引用的类的实例来判断具体调用哪个方法,这和上述的超类对象引用访问子类对象的机制相似。

举例说明:

//定义接口InterA 
interface InterA
{
  void fun();
}
//实现接口InterA的类B 
class B implements InterA
{
  public void fun()
  {
    System.out.println(“This is B”);
  }
}
//实现接口InterA的类C 
class C implements InterA
{
  public void fun()
  {
    System.out.println(“This is C”);
  }
}
class Test
{
  public static void main(String[] args)
  {
    InterA a;
    a= new B();
    a.fun();
    a = new C();
    a.fun();
  }
} 

输出结果为:

This is B

This is C

上例中类B和类C是实现接口InterA的两个类,分别实现了接口的方法fun(),通过将类B和类C的实例赋给接口引用a而实现了方法在运行时的动态绑定,充分利用了“一个接口,多个方法”展示了Java的动态多态性。

需要注意的一点是:Java在利用接口变量调用其实现类的对象的方法时,该方法必须已经在接口中被声明,而且在接口的实现类中该实现方法的类型和参数必须与接口中所定义的精确匹配。

结束语:以上就是java运行时多态性的实现方法,大家在编程过程中可以灵活运用,但是在性能要求较高的代码中不提倡运用运行时多态,毕竟Java的运行时动态方法调用较之普通的方法调用的系统开销是比较大的。

--------------------------------------------------

Java静态方法不具有多态性详解

动态绑定机制使得基类的引用能够指向正确的子类对象,从而使得面向基类编程成为可能。

然而动态绑定在以下两种情况会失效。

1、基类方法是private或final修饰的

这个很好理解,因为private说明该方法对子类是不可见的,子类再写一个同名的方法并不是对父类方法进行复写(Override),而是重新生成一个新的方法,也就不存在多态的问题了。同理也可以解释final,因为方法同样是不可覆盖的。

2、方法是static修饰的

代码如下所示.

class Base {
 public static void staticMethod() {
  System.out.println("Base staticMehtod");
 }

 public void dynamicMehtod() {
  System.out.println("Base dynamicMehtod");
 }
}

class Sub extends Base {
 public static void staticMethod() {
  System.out.println("Sub staticMehtod");
 }

 public void dynamicMehtod() {
  System.out.println("Sub dynamicMehtod");
 }
}

public class TJ4 {
 public static void main(String args[]) {
  Base c = new Sub();
  c.staticMethod();
  c.dynamicMehtod();
 }
}

输出结果如下:

 Base staticMehtod
 Sub dynamicMehtod

输出结果并不像设想的那样,输出 “Sub staticMehtod”。因为静态方法是与类而不是与某个对象相关联,c.staticMethod();等同于Car.staticMethod(); 所以尽量不要使用实例变量去调用静态方法,避免混淆。

以上这篇Java多态和实现接口的类的对象赋值给接口引用的方法(推荐)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java实现MapReduce对文件进行切分的示例代码

    java实现MapReduce对文件进行切分的示例代码

    本文主要介绍了java实现MapReduce对文件进行切分的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • 使用springBoot项目配置文件位置调整到打包外

    使用springBoot项目配置文件位置调整到打包外

    这篇文章主要介绍了使用springBoot项目配置文件位置调整到打包外,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-08-08
  • SpringBoot项目中Controller接收两个实体的实现方法

    SpringBoot项目中Controller接收两个实体的实现方法

    本文主要介绍了SpringBoot项目中Controller接收两个实体的实现方法,主要介绍了两种方法,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • Java并发框架:Executor API详解

    Java并发框架:Executor API详解

    这篇文章主要介绍了Java并发框架:Executor API详解,随着当今处理器中可用的核心数量的增加, 随着对实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行。 Java 提供了自己的多线程框架,称为 Executor 框架,需要的朋友可以参考下
    2019-07-07
  • SpringBoot validator参数验证restful自定义错误码响应方式

    SpringBoot validator参数验证restful自定义错误码响应方式

    这篇文章主要介绍了SpringBoot validator参数验证restful自定义错误码响应方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • SpringBoot 如何从容器中获取对象

    SpringBoot 如何从容器中获取对象

    这篇文章主要介绍了SpringBoot 如何从容器中获取对象,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 详解Springboot如何通过注解实现接口防刷

    详解Springboot如何通过注解实现接口防刷

    本文主要为大家介绍一种极简洁、灵活通用接口防刷实现方式、通过在需要防刷的方法加上@Prevent 注解即可实现短信防刷,感兴趣的可以了解一下
    2022-09-09
  • java PDF添加图层的方法 支持多页图层添加

    java PDF添加图层的方法 支持多页图层添加

    这篇文章主要为大家详细介绍了java PDF添加图层的方法,支持多页图层添加,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Java Swing组件编程之JTable表格用法实例详解

    Java Swing组件编程之JTable表格用法实例详解

    这篇文章主要介绍了Java Swing组件编程之JTable表格用法,结合实例形式详细分析了Swing组件中JTable表格的常见定义与使用方法,需要的朋友可以参考下
    2017-11-11
  • Maven Repository仓库的具体使用

    Maven Repository仓库的具体使用

    本文主要介绍了Maven Repository仓库的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05

最新评论