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

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

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

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);
   }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容