浅谈Java面向对象之内部类

 更新时间:2021年06月15日 08:50:27   作者:乌漆WhiteMoon  
内部类是一个非常有用的特性但又比较难理解使用的特性,我们从外面看是非常容易理解的,无非就是在一个类的内部在定义一个类。其实使用内部类最大的优点就在于它能够非常好的解决多重继承的问题

内部类

内部类是定义在另一个类中的类,例如 TalkingClock 类中内嵌了 TimePrinter 类:

class TalkingClock{
   private int interval;
   private boolean beep;
 
   public TalkingClock(int interval, boolean beep){}
   public void start(){}
 
   public class TimePrinter implements ActionListener{
      public void actionPerformed(ActionEvent event){}
   }
}

内部类可以对同一个包中的其他类隐藏细节,同时内部类中的方法可以访问原来的类中的作用域数据。

访问外部对象

内部类可以访问自身的数据字段,也可以访问创建它的外围类对象的数据字段。内部类会有一个隐式引用,指向创建它的外部类对象。


对外围类的引用在构造器中设置,编译器会修改所有内部类的构造器,添加一个对外部类引用的参数。使用外部类引用的语法为:

OuterClass.this

例如内部类 TimePrinter 引用外部类 TalkingClock 的 beep 参数,严格来说要写成这样。

TalkingClock.this.beep

访问内部对象

使用内部类的构造器时,可以使用下面的语法来实现:

outerObject.new InnerClass(construction parameters)

在外部类的作用域之外,想要引用内部类就需要用下面的语法:

OuterClass.InnerClass

局部内部类

局部内部类类似方法的局部变量,在类外或者类的其他方法中不能访问这个内部类。通常情况下可以在某个方法中局部实现一个类,这个类将用于辅助该方法的功能实现。例如:

public void start(){
      class TimePrinter implements ActionListener{
            public void actionPerformed(ActionEvent event){
                  System.out.println("The time is " + Instant.ofEpochMilli(event.getWhen()));
                  if (beep) {
                        Toolkit.getDefaultToolkit().beep();
                  }
            }
      }
 
      TimePrinter listener = new TimePrinter();
      TalkingClock timer = new Timer(interval, listener);
      timer.start();
} 

声明局部类时不能有访问说明符,局部类的作用域被限定在了这个局部类块中。局部类可以做到对外界的绝对隐藏,这是个很大的优势。
局部类还有个优点,就是可以访问局部变量。当局部变量传参进来时,局部变量也会被传入构造器,此时编译器会为局部变量提供相应的实例字段,保存一个副本。这么做的好处是,当函数调用结束导致局部变量消失时,局部类还能够使用这个局部变量。例如将上述的 start 方法改为传入 2 个参数,仍然不影响正常使用。

public void start(int interval, boolean beep)

匿名内部类

使用局部类时,如果只是想建立这个局部类的一个对象,甚至不需要给出这个类的名字,这种类就成为匿名内部类。匿名内部类的语法为:

new SuperType(construction parameters){
      inner class methods and data
}
 
new InterfaceType(){
      methods and data
}

SuperType 指的是超类,此时局部类就需要拓展这个类。匿名局部类可以基于接口创建,此时局部类就要实现这个接口。由于构造器的名字必须和类名相同,而匿名局部类没有类名,因此匿名局部类不能有构造器,此时如果要构造参数就需要传递给超类的构造器。例如将上述的局部类改造成匿名内部类:

public void start(){
      var listener = new ActionListener(){
               public void actionPerformed(ActionEvent event){
                  System.out.println("The time is " + Instant.ofEpochMilli(event.getWhen()));
                  if (beep) {
                        Toolkit.getDefaultToolkit().beep();
                  }
               } 
          }
      TalkingClock timer = new Timer(interval, listener);
      timer.start();
} 

静态内部类

有时候使用内部类只是想隐藏一个类,并不需要内部类有外部类的引用,因此可以用 static 关键字声明静态内部类。例如定义 ArrayAlg 类中实现 minmax 方法,minmax 方法的功能是同时返回一个数组的最大值和最小值,但是用 return 只能返回一个值。因此可以定义一个静态内部类 Pair,Pair 类有两个参数可以分别存储最大和最小值,这样就可以通过返回 Pair 方法同时返回 2 个值了。

class ArrayAlg{
   public static class Pair{
      private double first;
      private double second;
 
      public Pair(double f, double s){
         first = f;
         second = s;
      }
 
      public double getFirst() { return first; }
      public double getSecond() { return second; }
   }
 
   public static Pair minmax(double[] values){
      double min = Double.POSITIVE_INFINITY;
      double max = Double.NEGATIVE_INFINITY;
      for (double v : values){
         if (min > v) min = v;
         if (max < v) max = v;
      }
      return new Pair(min, max);
   }
}

只要内部类不需要访问外围类对象,就应该声明为静态内部类。和其他内部类不同,静态内部类可以有静态字段和方法。

以上就是浅谈Java面向对象之内部类的详细内容,更多关于Java面向对象内部类的资料请关注脚本之家其它相关文章!

相关文章

  • java面向对象设计原则之接口隔离原则示例详解

    java面向对象设计原则之接口隔离原则示例详解

    这篇文章主要为大家介绍了java面向对象设计原则之接口隔离原则的示例详解,有需要的朋友可以借鉴参考下希望能够有所帮助,祝大家多多进步早日升职加薪
    2021-10-10
  • java 设计模型之单例模式详解

    java 设计模型之单例模式详解

    本文主要介绍了java 单例模式,单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在,希望能帮助有需要的同学
    2016-07-07
  • Java中Map循环遍历的五种方法实现

    Java中Map循环遍历的五种方法实现

    本文主要介绍了Java中Map循环遍历的五种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • SpringBoot整合Mybatis使用Druid数据库连接池

    SpringBoot整合Mybatis使用Druid数据库连接池

    这篇文章主要介绍了SpringBoot整合Mybatis使用Druid数据库连接池,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • 一文带你掌握Java中的HashSet

    一文带你掌握Java中的HashSet

    HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合,HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的,本文将带你详细了解Java中的HashSet,,需要的朋友可以参考下
    2023-05-05
  • Spring Mybatis 分页插件使用教程

    Spring Mybatis 分页插件使用教程

    这篇文章主要介绍了Spring Mybatis分页插件使用教程,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-02-02
  • Java超详细讲解如何生成随机整数

    Java超详细讲解如何生成随机整数

    在 Java 中,生成随机数的场景有很多,所以本文我们就来盘点一下 几种生成随机数的方式,以及它们之间的区别和每种生成方式所对应的场景
    2022-05-05
  • Springcloud Bus消息总线原理是实现详解

    Springcloud Bus消息总线原理是实现详解

    Spring Cloud Bus 使用轻量级的消息代理来连接微服务架构中的各个服务,可以将其用于广播状态更改(例如配置中心配置更改)或其他管理指令,本文将对其用法进行详细介绍
    2022-09-09
  • java程序中protobuf的基本用法示例

    java程序中protobuf的基本用法示例

    这篇文章主要给大家介绍了关于java程序中protobuf的基本用法,protobuf 与json相比具有 压缩比高 、解压缩速度更快的优点,本文通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-08-08
  • SpringBoot项目@Async方法问题解决方案

    SpringBoot项目@Async方法问题解决方案

    这篇文章主要介绍了SpringBoot项目@Async方法问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04

最新评论