• Java 面向对象:内部类


    禁止码迷,布布扣,豌豆代理,码农教程,爱码网等第三方爬虫网站爬取!

    内部类

    内部类是定义在另一个类中的类,例如 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 核心技术 卷Ⅰ》,[美]Cay S.Horstmann 著,林琪 苏钰涵 等译,机械工业出版社

  • 相关阅读:
    QQ企业通--客户端登陆模块设计---知识点2
    C# Show()与ShowDialog()的区别-----转载
    docker入门学习
    人生感悟
    mysql权限管理命令
    JAVA程序员工作常用英语(细心整理)
    spring知识梳理
    快速搭建MHA
    MySQL Performance Schema都建议开启哪些监控采集指标(除了默认自动开启的指标)
    慢SQL引发MySQL高可用切换排查全过程
  • 原文地址:https://www.cnblogs.com/linfangnan/p/13463506.html
Copyright © 2020-2023  润新知