Java基础之内部类

举报
码农飞哥 发表于 2021/05/29 12:30:33 2021/05/29
【摘要】 内部类的简介 内部类是定义在另一个类中的类。 内部类的使用场景 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。内部类可以对同一个包中的其他类隐藏起来。当想要定义一个回调函数且不想大量编写代码是时,使用匿名内部类比较便捷 下面我们看一个简单程序 package com.jay.innerClass; import javax.swing.*; ...

内部类的简介

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

内部类的使用场景

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

下面我们看一个简单程序

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

在说明2中,我们看到了内部类直接引用了外部类的been变量。这里他是如何能引用的呢?
我们将外围类对象的引用称为outer。(outer不是Java的关键字)
外围类的引用在构造器中设置。编译器修改了所有内部类的构造器。添加了一个外部类引用的参数。
如上例中,编译器为这个类生成了一个默认的构造器。其代码如下:

  public TimerPrint(TalkingClock clock){ outer=clock
  }
  
 
  • 1
  • 2
  • 3

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

内部类的特殊语法规则

  1. 内部类中声明的所有静态域都必须是final,原因很简单。我们希望一个静态域只有一个实例,不过对于每个外部对象,
    会分别有一个单独的内部类实例。如果这个域不是final,它可能就不是唯一的。
  2. 内部类中不能有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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

该方法的控制流程是
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"); } } 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

可以替代的方案是:

 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"); } }
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

匿名内部类

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

文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。

原文链接:feige.blog.csdn.net/article/details/79191404

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。