第六章 内部类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37726222/article/details/84616370

为什么要使用内部类?

  • 内部类可以访问该类定义所在的作用域中的所有的数据,包括私有数据
  • 内部类可以对同一个包的其他类隐藏起来
  • 当要定义一个回调函数并且不想编写大量代码时,使用匿名内部类比较方便。

使用内部类访问对象的状态

内部类的对象总有一个隐式引用。它指向了创建它的外部类对象。
在一个内部类的对象被创建之时,它所在类的对象的引用被作为参数,传递给这个内部类的隐式构造函数。

内部类的特殊语法规则

  • OuterClass.this 引用外部类的对象 egTalking.this.beep
  • ActionListener listenr =this.new TimePrinter();在这里,最新构造的actionListener对象的外围类的引用被设置为创建内部类对象的方法中的this引用。
  • 在外围类的作用域之外,Outerclass.innerclass可以这样引用内部类
  • 内部类中所有的静态域必须是final

内部类是否有用,必要和安全?

与常规类相比,内部类访问外围类私有数据的特性更强大

内部实现?

  • 编译器会在外围类中添加static boolean access$0(TalkingClock) 这样的access$0方法

局部内部类

局部内部类适用于内部类的对象只使用一次的情况。

  • 局部类不能用public 或 private修饰。
  • 局部类的优势是,只在一个方法内定义,只被一个方法使用。其他类不知道该局部类的存在。

由外部方法访问变量 P252

与内部类相比较,局部类的另一个优点是,可以访问局部变量。
局部类的方法只可以引用定义为final的局部变量。对于counter这种final不方便的情况,可以用长为1的数组来存储。

匿名内部类

匿名内部类的格式?

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

注意匿名类没有类名。故没有构造器。
如果有参数,作用是啥?参数传递给超类的构造器。(上面就是个例子)
但是,对于内部类实现接口的时候:不能有参数!

new InterfaceType()
{
	inner class methods and data;
}

下面是用匿名内部类实现语音时钟程序的源代码:

/**
 * A clock that prints the time in regular intervals.
 */
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();
   }
}

但此处用lambda表达式会更加的简洁。

小注释:匿名数组列表:

invite
(
	new ArrayList<String>()
	{
		{  
			add("Harry");
			add("Tony");
		}
	}
)

匿名子类在使用equals方法时要特别当心!
getClass()方法在使用时调用的是this.getClass(),但是静态方法没有内部类,这就不行了
怎么办?

new Object(){}.getClass.getEnclosingClass()

这样就得到了包含这个静态方法的类。可以算是匿名子类的一个应用吧。

静态内部类

为什么要静态?
有时候不需要内部类引用外围类的对象,所以声明该内部类为static,取消产生引用。
静态内部类的对象除了没有对生成它的外围类对象的引用特权外,与其他所有内部类完全一样。

与常规内部类不同,静态内部类可以有静态域和方法。
下面是一个静态内部类的例子:

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);
   }
}

下面是调用的方法:

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());
   }

注意此处,内部类对象在静态方法中构造,所以必须使用静态内部类

猜你喜欢

转载自blog.csdn.net/weixin_37726222/article/details/84616370