内部类

作者: 爱做梦的严重精神病患者 | 来源:发表于2018-12-02 11:48 被阅读0次

    1.内部类介绍及使用原因

    内部类定义在另一个类中。使用内部类的主要原因如下(若A为B的内部类):

    • A可以访问B中的数据,包括私有数据。
    • 内部类可以一个包中的其他类隐藏
    • 当想要定义一个回调函数且不想编写大量代码时,可以使用匿名内部类

     需要注意的是:虽然A为B的内部类,但是并不意味每个B类对象都有同一个A的实例域

     内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。这是由于内部类的对象总有一个隐式引用,它指向了创建它的外部类对象。这个引用在内部类的定义中是不可见的。
    内部类内使用this参数的是内部类自己,而要使用外部类的this参数,需要使用OuterClass.this

    内部类可以访问外围类的所有域,那它是如何管理这些额外的访问特权呢?
    class TalkingClock{
    private int interval;
    private boolean beep;
    
    public TalkingClock();
    
    这个方法是编译器在外围类中添加的,
    由于内部类会访问beep变量,所以添加了这个方法。
    内部类调用这个方法,将会得到返回的beep变量的值。
    static boolean access$00(TalkingClock);
    
    public void start();
    }
    

    内部类中声明的所有静态域都必须是final。因为,一个静态域只有一个实例。不过对于每个外部类对象,会分别由一个单独的内部类实例。如果这个内部类的静态域不是final,就有可能不是唯一。


    2.局部内部类

    定义在方法中的内部类

    public void start() {
        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();
            Time t = new Timer(interval, listener);
            t.start();
    }
    

    局部类不能用public或private进行修饰,局部类对外部完全隐藏,除了start()方法之外,没人知道TimePrinter类的存在。
    局部类不仅可以访问包含它们的外部类,还可以访问局部变量。但局部变量必须为final

    public void start(int interval, final 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();
            Time t = new Timer(interval, listener);
            t.start();
    }
    
    整体流程:
    1.调用start方法
    2.调用内部类的TimePrinter构造器。初始化listener对象。
    3.将listener引用传递给Timer构造器,定时器开始计时,start方法结束。
    此时,start方法的变量beep也不存在了。
    4.actionPerformed方法执行if(beep)
    5.为了能让actionPerformed方法工作,TimePrinter类在beep域释放之前(方法刚开始时)
    将beep域用start()方法的局部变量进行备份。
    将beep参数声明为final,对它进行初始化后不能再修改。
    因此就使得局部变量与在局部类内建立的拷贝保持一致。
    

     有时,final限制显得很不方便。可以使用长度为1的数组来代替局部变量。

    final int[] counter = new int[1];
    Date [] dates = new Date[100];
    for (int i = 0; i < dates.length; i++)
       dates[i] = new Date() {
            public int compareTo(Date other) {
                counter[0]++;
                return super.compareTo(other);
                }
          };
    Arrays.sort(dates);
    System.out.println(counter[0] + "comparisons.");
    

    3.匿名内部类

    匿名内部类一般用在创建实现了某个接口(或扩展某个类)的对象上,直接使用关键字new这个接口(或这个父类)。
    匿名内部类没有名字,所以也没有构造器。然而,当匿名内部类扩展某个父类的时候,可以将构造器参数传递给父类

     语法格式:

    new SuperType(constructor parameters){
          inner class methods and data
    }
    
    new InterfaceType() {
        methods and data
    }
    
    创建一个person对象
    Person queen = new Person("Marry");
    
    创建一个扩展了person类的匿名内部类对象
    Person count = new Person("Dracula") {....};
    
    
    创建一个实现ActionListener接口的类的新对象,需要实现的方法actionPerformed定义在{ }内
    public void start(int interval, final 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();
              } 
       };
            Time t = new Timer(interval, listener);
            t.start();
    }
    
    

     通常用匿名内部类实现事件监听器和其他回调,如今大多数使用lambda表达式


    4.静态内部类

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

     因为静态内部类外部类的类相关的,而不是外部类的对象相关的。也就是说,静态内部类对象不是寄生在外部类的实例中,而是寄生在外部类的类本身中

    静态内部类只能访问外部类的静态成员。生成(new)一个静态内部类对象不需要外部类成员:这是静态内部类和成员内部类的区别静态内部类的对象可以直接生成:Outer.Inner in=new Outer.Inner();而不需要通过生成外部类对象来生成(类似于静态成员不需要new对象就可直接使用)。

     成员内部类的对象生成:

    Outer out = new Outer();
    Outer.Inner in = outer.new Inner();
    

    相关文章

      网友评论

          本文标题:内部类

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