Java基础之内部类

简介: 内部类是定义在另一个类中的类。

内部类的简介


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


内部类的使用场景

内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。

内部类可以对同一个包中的其他类隐藏起来。

当想要定义一个回调函数且不想大量编写代码是时,使用匿名内部类比较便捷

下面我们看一个简单程序


package com.jay.innerClass;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
/**
 * Created by xiang.wei on 2018/1/26
 * 描述:构造一个语音时钟
 * @author xiang.wei
 */
public class InnerClassTest {
    public static void main(String[] args) {
        TalkingClock talkingClock = new TalkingClock(1000, true);
        talkingClock.start();
        JOptionPane.showMessageDialog(null,"Quit program?");
    }
}
class TalkingClock {
    /**
     * 发布通告的时间间隔
     */
    private int interval;
    /**
     * 开关铃声的标志
     */
    private boolean beep;
    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();
    }
    public class TimePrinter implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("At the tone,the time is" + new Date());
            //说明2
            if (beep) {
                Toolkit.getDefaultToolkit().beep();
            }
        }
    }
}


在说明2中,我们看到了内部类直接引用了外部类的been变量。这里他是如何能引用的呢?

我们将外围类对象的引用称为outer。(outer不是Java的关键字)

外围类的引用在构造器中设置。编译器修改了所有内部类的构造器。添加了一个外部类引用的参数。

如上例中,编译器为这个类生成了一个默认的构造器。其代码如下:

public TimerPrint(TalkingClock clock){
    outer=clock
  }


当在start 方法中创建了TimerPrinter对象后,编译器就会将this引用传递给当前的语音时钟的构造器

ActionListener listener = new TimerPrinter(this)


内部类的特殊语法规则

内部类中声明的所有静态域都必须是final,原因很简单。我们希望一个静态域只有一个实例,不过对于每个外部对象,

会分别有一个单独的内部类实例。如果这个域不是final,它可能就不是唯一的。

内部类中不能有static方法。Java语言规范对这个限制没有做任何解释。也可以允许有静态方法,但只能访问外部类的静态域

和方法。

局部内部类

局部内部类就是在方法内部定义的一个内部类。对外部世界是完全隐藏起来的。即使是外部类类本身的其他的方法也不能访问

如下例所示:

public void start() {
    class TimePrinter implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("At the tone,the time is" + new Date());
            if (beep) {
                Toolkit.getDefaultToolkit().beep();
            }
        }
    }
    ActionListener listener = new TimePrinter();
    javax.swing.Timer timer = new javax.swing.Timer(interval, listener);
    timer.start();
}


该方法的控制流程是

1. 调用start方法

2. 调用内部类TimePrinter的构造器,以便初始化对象listener

3. 将listener引用传递给Timer构造器,定时器开始计时,start方法结束,此时start

方法的beep参数变量不复存在。

4. 然后,actionPerformed 方法执行if(beep)…


假设想更新在一个封闭作用域内的计数器。这里想要统计一下在排序过程中调用

compareTo 方法的次数

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


可以替代的方案是:

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


匿名内部类

只创建了一个类的一个对象。

由于构造器的名字必须与类名相同,而匿名内部类没有类名。所以,匿名类不能有构造器。取而代之的是,将构造器参数

传递给超类构造器。尤其是在内部类实现接口的时候,不能有任何构造参数。


相关文章
|
2月前
|
Java
【Java基础面试二】、个Java文件里可以有多个类吗(不含内部类)?
这篇文章讨论了Java文件中类的定义规则,指出一个Java文件可以包含多个类(不包含内部类),但其中最多只能有一个public类,且如果有public类,它的名称必须与文件名一致。
|
2月前
|
算法 Java
12 Java常用类(一)(内部类+object类+包装类)
12 Java常用类(一)(内部类+object类+包装类)
29 5
|
3月前
|
Java
Java进阶之内部类
【7月更文挑战第13天】Java内部类增进代码组织与封装,允许直接访问外部类成员,包括私有成员。主要有四种类型:成员、静态、局部和匿名内部类。匿名内部类常用于一次性实现接口或扩展类。内部类可隐藏实现细节,减少命名冲突,并在特定上下文中定义辅助类。示例展示了静态和非静态内部类如何在Shape类中封装Circle和Rectangle。使用内部类能提升代码可读性,但可能增加复杂性。
33 6
|
2月前
|
Java
【Java】内部类、枚举、泛型
【Java】内部类、枚举、泛型
|
4月前
|
Java
一篇文章讲明白Java中内部类详解—匿名内部类
一篇文章讲明白Java中内部类详解—匿名内部类
52 2
|
4月前
|
设计模式 Java 编译器
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
|
4月前
|
Java 编译器
24. 【Java教程】内部类
24. 【Java教程】内部类
24 2
|
5月前
|
Java 程序员
Java的内部类与匿名类的技术性文章
Java的内部类与匿名类的技术性文章
36 1
|
4月前
|
Java
Java内部类相关内容总结和解读
Java内部类相关内容总结和解读
28 0
|
4月前
|
存储 Java
Java 五种内部类演示及底层原理详解
Java 五种内部类演示及底层原理详解
27 0
下一篇
无影云桌面