美文网首页
Java核心技术(卷I) 15、内部类

Java核心技术(卷I) 15、内部类

作者: kaiker | 来源:发表于2021-03-13 18:15 被阅读0次

    内部类是定义在另一个类中的类

    • 可以对同一个包中的其他类隐藏
    • 可以访问定义这个类的作用域中的数据,包括原本私有数据

    https://www.zhihu.com/question/26954130 这个讲得很好

    1、对象类访问对象状态

    这个beep并不是TimePrinter的对象,但是TimePrinter作为内部类可以访问

    class TalkingClock
    {
       private int interval;
       private boolean beep;
    
       /**
        * Constructs a talking clock
        * @param interval the interval between messages (in milliseconds)
        * @param beep true if the clock should beep
        */
       public TalkingClock(int interval, boolean beep)
       {
          this.interval = interval;
          this.beep = beep;
       }
    
       /**
        * Starts the clock.
        */
       public void start()
       {
          ActionListener listener = new TimePrinter();
          Timer t = new Timer(interval, listener);
          t.start();
       }
    
       public class TimePrinter implements ActionListener
       {
          public void actionPerformed(ActionEvent event)
          {
             System.out.println("At the tone, the time is " + new Date());
             if (beep) Toolkit.getDefaultToolkit().beep();
          }
       }
    }
    
    内部类对象有一个外围类对象引用
    • 外围类的引用在构造器中设置。编译器会修改所有内部类构造器,添加一个对应外围类引用的参数。
    public TimePrinter(TalkingClock clock){
      outer = clock;
    }
    
    • 虚拟机会把内部类转换为常规文件,用$分隔外部类名和内部类名
    public class innerClass.TalkingClock$TimePrinter {
      final innerClass.TalkingClock this$0;
    }
    

    2、局部内部类

    • 声明不能有访问说明符
    • 对外部完全隐藏
    • 可以访问是事实最终变量的局部变量,比如下面的beep就不再是TalkingClock的变量了(局部变量是随着方法的调用而调用,使用完毕就消失,而堆内存的数据并不会立即消失 https://www.zhihu.com/question/26954130
    class TalkingClock
    {
       /**
        * Starts the clock.
        * @param interval the interval between messages (in milliseconds)
        * @param beep true if the clock should beep
        */
       public void start(int interval, boolean beep)
       {
          class TimePrinter implements ActionListener
          {
             public void actionPerformed(ActionEvent event)
             {
                System.out.println("At the tone, the time is " + new Date());
                if (beep) Toolkit.getDefaultToolkit().beep();
             }
          }
          ActionListener listener = new TimePrinter();
          Timer t = new Timer(interval, listener);
          t.start();
       }
    }
    
    • 编译器处理成
    Class TalkingClock$TimePrinter {
      TalkingClock$TimePrinter(TalkingClock, boolean);
      final boolean val$beep;
    }
    

    3、匿名内部类

    • 如果只是想创建这个类的一个对象,可以不为类指定名字
    • 使用lambda表达式会更好
    class TalkingClock
    {
       /**
        * Starts the clock.
        * @param interval the interval between messages (in milliseconds)
        * @param beep true if the clock should beep
        */
       public void start(int interval, boolean beep)
       {
          ActionListener listener = new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   System.out.println("At the tone, the time is " + new Date());
                   if (beep) Toolkit.getDefaultToolkit().beep();
                }
             };
          Timer t = new Timer(interval, listener);
          t.start();
       }
    }
    

    4、静态内部类

    • 只是为了把一个类隐藏在另一个类的内部,并不需要内部类有外围类对象的引用,可以使用静态内部类
    • 没有外部类对象,也可以创建静态内部类对象 https://www.zhihu.com/question/26954130
    • 下面这个例子里,不需要构建ArrayAlg的对象,可以通过ArrayAlg.Pair p调用
    public class StaticInnerClassTest
    {
       public static void main(String[] args)
       {
          double[] d = new double[20];
          for (int i = 0; i < d.length; i++)
             d[i] = 100 * Math.random();
          ArrayAlg.Pair p = ArrayAlg.minmax(d);
          System.out.println("min = " + p.getFirst());
          System.out.println("max = " + p.getSecond());
       }
    }
    
    class ArrayAlg
    {
       /**
        * A pair of floating-point numbers
        */
       public static class Pair
       {
          private double first;
          private double second;
    
          /**
           * Constructs a pair from two floating-point numbers
           * @param f the first number
           * @param s the second number
           */
          public Pair(double f, double s)
          {
             first = f;
             second = s;
          }
    
          /**
           * Returns the first number of the pair
           * @return the first number
           */
          public double getFirst()
          {
             return first;
          }
    
          /**
           * Returns the second number of the pair
           * @return the second number
           */
          public double getSecond()
          {
             return second;
          }
       }
    
       /**
        * Computes both the minimum and the maximum of an array
        * @param values an array of floating-point numbers
        * @return a pair whose first element is the minimum and whose second element
        * is the maximum
        */
       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核心技术(卷I) 15、内部类

          本文链接:https://www.haomeiwen.com/subject/pqpxcltx.html