zoukankan      html  css  js  c++  java
  • Core Java笔记 5.内部类

    本章重点:

    • 为何使用内部类
    • 访问外围类数据
    • 内部类的语法规则
    • 局部内部类
    • 匿名内部类

    内部类(inner class)是定义在另一个类中的类。
    

    为何使用内部类

    1. 内部类方法可以访问外围类的数据,包括私有的数据.
    2. 内部类可以对同一个包种的其他类隐藏起来.
    3. 使用anonymous内部类定义回调函数类.

    访问外围类数据

    示例:

    package corejava.inner;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Date;
    
    /**
     * Created by guolong.fan on 15/4/26.
     */
    public class InnerClassTest {
    
        public static void main(String[] args) {
            TalkingClock clock = new TalkingClock(1000, true);
            clock.start();
    
            JOptionPane.showMessageDialog(null, "Quit program?");
            System.exit(0);
        }
    }
    
    class TalkingClock {
    
        public TalkingClock(int interval, boolean beep) {
            this.interval = interval;
            this.beep = beep;
        }
    
        public void start() {
            ActionListener listener = new TimePrinter();
            Timer timer = new Timer(interval, listener);
            timer.start();
        }
    
        private int interval;
        private boolean beep;
    
        public class TimePrinter implements ActionListener {
    
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("At the tone, the time is " + new Date());
                if (beep) Toolkit.getDefaultToolkit().beep();
            }
        }
    }
    

    if (beep)... 访问了外围类的私有属性.

    内部类是一种编译器现象,与虚拟机无关. 使用 javap 分析编译器如何生成代码的?
    javap -private TalkingClock$TimePrinter.class

    • 内部类的命名. outclass$innerclass(eg. TalkingClock$TimePrinter)
    • 内部类生成外部类实例的引用(final)+构造器.
    public class corejava.inner.TalkingClock$TimePrinter extends java.lang.Object implements java.awt.event.ActionListener{
        final corejava.inner.TalkingClock this$0;
        public corejava.inner.TalkingClock$TimePrinter(corejava.inner.TalkingClock);
        public void actionPerformed(java.awt.event.ActionEvent);
    }
    
    • 针对内部类访问了的private fields, 外围类生成 access$ 代码(package权限的getter).
    class corejava.inner.TalkingClock extends java.lang.Object{
        private int interval;
        private boolean beep;
        public corejava.inner.TalkingClock(int, boolean);
        public void start();
        static boolean access$000(corejava.inner.TalkingClock);
    }
    

    最终,编译器生成如下代码.

    class TalkingClock {
    
        public TalkingClock(int interval, boolean beep) {
            this.interval = interval;
            this.beep = beep;
        }
    
        public void start() {
            ActionListener listener = new TimePrinter(this);
            Timer timer = new Timer(interval, listener);
            timer.start();
        }
    
        static boolean access$000(corejava.inner.TalkingClock);
        
        private int interval;
        private boolean beep;
    
        public class TimePrinter implements ActionListener {
            public TimePrinter(TalkingClock clock) {
                outer = clock;
            }
    
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("At the tone, the time is " + new Date());
                if (access$000()) Toolkit.getDefaultToolkit().beep();
            }
            ...
            private TalkingClock outer;
        }
    }
    

    内部类的语法规则

    1. 外围类的引用. 即上面的 outer 实质是 OuterClass.this. beep可以写成TalkingClock.this.beep.
    2. 生成内部类对象. outObject.new InnerClass(construction parameters).
    内部类:
    ActionListener listener = this.new TimePrinter();
    
    其他程序中:
    TalkingClock jabberer = new TalkingClock(1000, true);
    TalkingClock.TimePrinter listener = jabberer.new TimePrinter();
    

    局部内部类

    直接定义在方法中.

    public class InnerClassTest {
    
        public static void main(String[] args) {
            TalkingClock clock = new TalkingClock(1000, true);
            clock.start();
    
            JOptionPane.showMessageDialog(null, "Quit program?");
            System.exit(0);
        }
    }
    
    class TalkingClock {
    
        public TalkingClock(int interval, boolean beep) {
            this.interval = interval;
            this.beep = beep;
        }
    
        public void start() {
            public class TimePrinter implements ActionListener {
    
                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                    System.out.println("At the tone, the time is " + new Date());
                    if (beep) Toolkit.getDefaultToolkit().beep();
                }
            }   
        
            ActionListener listener = new TimePrinter();
            Timer timer = new Timer(interval, listener);
            timer.start();
        }
    
        private int interval;
        private boolean beep;
    }
    
    

    匿名内部类

    package corejava.inner;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Date;
    
    /**
     * Created by guolong.fan on 15/4/26.
     */
    public class InnerClassTest {
    
        public static void main(String[] args) {
            TalkingClock clock = new TalkingClock(1000, true);
            clock.start();
    
            JOptionPane.showMessageDialog(null, "Quit program?");
            System.exit(0);
        }
    }
    
    class TalkingClock {
    
        public TalkingClock(int interval, boolean beep) {
            this.interval = interval;
            this.beep = beep;
        }
    
        public void start() {
            ActionListener listener = new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                    System.out.println("At the tone, the time is " + new Date());
                    if (beep) Toolkit.getDefaultToolkit().beep();
                }
            };
    
            Timer timer = new Timer(interval, listener);
            timer.start();
        }
    
        private int interval;
        private boolean beep;
    }
    
  • 相关阅读:
    【宋红康程序思想学习日记5】数组排序之冒泡法
    求割点 poj 1523
    网络流 poj 3308 最小割
    网络流最小割 POJ 3469
    网络流 POJ2112
    网络流 HDU 3605
    网络流HDU 2883
    网络流 最大流HDU 3549
    微信公众平台开发者中心服务器配置Token验证失败问题
    排列熵算法简介及c#实现
  • 原文地址:https://www.cnblogs.com/nil2inf/p/4469236.html
Copyright © 2011-2022 走看看