6.4 内部类

为什么使用内部类

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

嵌套是一种类之间的关系,而不是对象之间的关系。

嵌套类的好处:

  • 命名控制;
  • 访问控制;

内部类是由外部类的方法构造。
内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TalkingClock {
   
  private int interval;

  private boolean beep;


  public class TimerPrinter implements ActionListener{

       @Override
       public void actionPerformed(ActionEvent e) {
          System.out.println("The time is: " + new Date());
           if(beep){//相当于outer.beep
               Toolkit.getDefaultToolkit().beep();
           }
       }
   }
}

外围类的引用在构造器中设置

public TimerPrinter(TalkingClock clock){
   outer = clock; 
}

outer不是Java中的关键字

6.4.2内部类的特殊语法规则

使用外围类引用内部类
表达式:OuterClass.this

outerObject.new InnerClass(construction parameters)

例如

ActionListener listener = this.new TimePrinter();

在外围类的作用域之外,可以这样引用内部类:

OuterClass.InnerClass

内部类可以直接使用外部类的域(使用beep,也可以使用OuterClass.this.beep)

内部类所有声明的静态域都必须是final。
内部类不能有static方法。

6.4.3内部类是否有用、必要和安全

内部类时一种编译器现象与虚拟机无关。
内部类可以访问外部类的私有数据。

6.4.4局部内部类

局部类不能使用public或private访问符进行声明。
局部类的优势时对外部世界可以完全隐藏起来。即使外部类中的其它方法也不能访问它。

   public void start(){
        class TimePrinter implements ActionListener{

           @Override
           public void actionPerformed(ActionEvent e) {
               System.out.println("哈哈哈"+ new Date());

               if (TalkingClock.this.beep) Toolkit.getDefaultToolkit().beep();
           }
       }
       
       ActionListener actionListener = new TimePrinter();
       Timer t = new Timer(interval,actionListener);
       t.start();
   }

6.4.5由外部方法访问变量

局部类不仅可以访问包含他们的外部类,还可以访问局部变量(但是局部变量必须为final)。

   public void start(int interval,boolean beep){
        class TimePrinter implements ActionListener{

           @Override
           public void actionPerformed(ActionEvent e) {
               System.out.println("哈哈哈"+ new Date());

               if (TalkingClock.this.beep) Toolkit.getDefaultToolkit().beep();
           }
       }
       
       ActionListener actionListener = new TimePrinter();
       Timer t = new Timer(interval,actionListener);
       t.start();
   }

6.4.6匿名内部类

由于构造器的名字必须与类名相同,而匿名类没有类名,所以匿名类不能有构造器。取而代之的是将构造器参数传递给超类(superclass)构造器。尤其是在内部类实现接口的时候,不能有任何构造参数。

6.4.7静态内部类

有时候,内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类的对象。为此,可以将内部类声明为static,以便取消产生的引用。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Pair {

   private double first;

   private double second;

   public static void main(String[] args) {
       double [] d = {34.5d,7.34d,3432.76d,999.333d};
       Pair pair = ArrayAlg.minmax(d);
       System.out.println(pair.getFirst());
       System.out.println(pair.getSecond());
   }
}
class  ArrayAlg{
   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);
   }
}

只有内部类可以声明为static。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值