`
DBear
  • 浏览: 232738 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类

Inner Classes小结

阅读更多

   Inner Classes 在平常的应用中虽然不是很多,但是仍然有很多细节问题值得注意,需要掌握。因此,这里对这方面内容做一小结。

   Inner Classes,顾名思义,就是定义在另一个类中的类,之所以出现这一概念,主要是因为它具有如下两个特点:  

  1. inner classes中的方法可以访问类定义域内的所有数据, 哪怕数据是private的。
  2. inner classes对同包内的其它类是不可见的。

   常规内部类

   下面,我将针对一段具体代码,对Inner Classes的特性和应用作具体的阐述。

public class TimerTestForInnerClass {
    public static void main(String[] args) {
        TalkingClock clock = new TalkingClock(100, true);
        clock.start();
	
        JOptionPane.showMessageDialog(null, "Quit Program?");
        System.exit(0);
    }
}

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 t = new Timer(interval, listener);
      t.start();
  }
  
  public class TimePrinter implements ActionListener {
      public void actionPerformed(ActionEvent event) {
          Date now = new Date();
          System.out.println("At the tone, the time is " + now);
          if (beep) Toolkit.getDefaultToolkit().beep();
      }
  }
  
}

 

    在上面的代码中,TimePrinter是TalkingClock的内部类。仔细观察,发现actionPerformed方法中引用的beep变量在TimePrinter中并没有定义,它是外部类TalkingClock的成员变量。这就是inner classes特点一的展示,之所以可以如此,是因为inner class在被创建时获得了外部类的一个引用,这个引用是由编译器自动传给内部类的构造函数的,因此,内部类中使用的beep变量的完整形式其实是:

 

if (TalkingClock.this.beep) Toolkit.getDefaultToolkit().beep();

   上述代码中的OuterClass.this代表的就是外部类的引用。

   如果内部类是public的,那么我们也可以在外部类以外来创建内部类,方法如下:

TalkingClock jabberer = new TalkingClock(1000, true);
TalkingClock.TimePrinter listener = jabberer.new TimePrinter();

  

Local Inner Classes 局部内部类

   内部类除了可以作为外部类的成员,还可以定义在外部类的方法中,这样的内部类称为:Local Inner Classes。Local Inner Classes不需要访问权限修饰符(access specifier),因为它们的作用域受它们被定义的块域的限制。Local Inner Classes的一个重要的优点是,除了定义它们的方法以外,外界任何类或方法都无法访问它们。因此,当一个内部类只需要被一个方法使用,并且想屏蔽任何其他方法时,就可以将它们定义为Local的。

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

   上面的代码就是Local Inner Class的应用实例。

   

    Local Inner Class不光可以使用Outer Class的成员变量,还可使用它所在方法的参数以及方法中的局部变量。但要注意一点,这些外部引用变量都必须是final型,否则会收到编译器错误。见下面的代码:

public void start(int interval, final boolean beep) {
    class TimePrinter implements ActionListener {
      public void actionPerformed(ActionEvent event) {
          Date now = new Date();
          System.out.println("At the tone, the time is " + now);
          if (beep) Toolkit.getDefaultToolkit().beep();
      }
    }
    ActionListener listener = new TimePrinter();
    Timer t = new Timer(interval, listener);
    t.start();
}

   我们来简单了解下beep参数是如何传入内部类的方法中。直观来看,beep变量是无法存留到actionPerformed方法执行之时的,它在start()方法执行结束之后就被回收了,而actionPerformed则要过短时间才执行,因此,为了正常使用beep变量,我们需要为它做一个copy,并将这个copy传进内部类中。所以,内部类中所谓的beep,其实是原有变量的副本。

 

TIP:为什么只有final型的参数或局部变量可以传入inner class?(整理自Core Java,如有不妥,敬请指正)

在很多时候,这个final的限制其实为我们带来了很多不便,因为我们有的时候确实是想要在inner class中改变局部变量的,如下面这段代码:

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.");

 

   我们只是想获取比较次数,但是由于内部类的final限制,这样的代码显然是不合法的。但如果直接加上final,我们的update目标又无法达到,所以,只能做如下的转换:

final int[] counter = new int[1];
for (int i = 0; i < dates.length; i++)
   dates[i] = new Date() {
          public int compareTo(Date other) {
              counter[0]++;
              return super.compareTo(other);
          }
   };

    这样,虽然counter是final的,但是我们却可以随意改变它内部的值,从而变相的达到了update的目标。

    事实上,在inner class起初创建时,这种从primitive型到array型的转换最开始是由编译器自动完成的,但是开发者们很害怕编译器在“背着他们”创建那么些对象,因此,最后还是决定加上final这个限制,如果需要在inner class中改变变量值,那就让programer自己去做转换。而且,也并不排除,随着Java语言的不断完善,会有更好的方式来替代final限制,达到原有的安全效果。

  

分享到:
评论

相关推荐

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    3.4 小结:基本数据类型—— Java中一切数据和运算的基础 63 3.5 习题 65 第4章 Java中的程序执行流程 67 教学视频:1小时57分钟 4.1 顺序执行 67 4.2 使用if-else让程序懂得判断 68 4.2.1 if语句 68 4.2.2 ...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    3.4 小结:基本数据类型—— Java中一切数据和运算的基础 63 3.5 习题 65 第4章 Java中的程序执行流程 67 教学视频:1小时57分钟 4.1 顺序执行 67 4.2 使用if-else让程序懂得判断 68 4.2.1 if语句 68 4.2.2 ...

    java接口与内部类

    #### 小结 - **接口**是Java中用于定义行为规范的重要工具,它增强了程序的扩展性和灵活性。 - **内部类**则提供了更加灵活的面向对象编程方式,能够更好地组织和复用代码。 - 通过理解和应用接口与内部类的概念,...

    基于MATLAB的风光氢多主体能源系统合作运行:纳什谈判与ADMM算法的应用

    内容概要:本文详细介绍了基于MATLAB平台的‘风-光-氢’多主体能源系统合作运行方法,利用纳什谈判理论和交替方向乘子法(ADMM)解决了传统集中式优化忽视个体利益的问题。文中首先设置了各能源主体的成本特性函数,并通过双层分解策略将复杂问题拆解为可分布式计算的子问题,确保了收敛性和求解效率。接着,文章展示了ADMM主循环和主体优化求解函数的具体实现,强调了并行计算、自适应步长调整以及全局变量更新的重要性。最后,通过仿真结果表明,合作博弈模式下联盟总效益提升了23.7%,各主体收益均满足个体理性条件。 适合人群:从事能源系统优化、分布式计算、博弈论应用的研究人员和技术人员。 使用场景及目标:适用于需要解决多主体能源系统中利益分配和协同优化问题的场景,旨在提高能源系统的整体效益和个体满意度。 其他说明:代码中引入了机会成本模型、自适应步长调整机制、鲁棒性校验模块等改进措施,使得模型更加贴近实际市场情况。此外,代码采用了面向对象结构,增强了扩展性和实用性。

    计算机二级C语言知识复习资料-知识清单-复习要点

    包含了C语言的重要知识点,常见考点。

    活动创作者激励数据相关材料

    【活动】创作者激励数据相关材料

    电影评论网站系统设计与实现.zip

    Java项目基于Springboot框架的课程设计,包含LW+ppt

    【计算机求职笔试】资源

    【计算机求职笔试】资源

    基于模糊神经网络的风光储联合并网系统中123级负荷功率分配Simulink/Matlab仿真

    内容概要:本文详细介绍了利用模糊神经网络进行风光储联合并网系统中123级负荷功率分配的Simulink/Matlab仿真模型。该模型将光伏、风机的最大功率点跟踪(MPPT)与虚拟同步发电机(VSC)并网技术相结合,通过模糊神经网络控制器实现对不同优先级负荷的智能分配。文中具体阐述了负荷分级策略、模糊控制器的设计、MPPT算法优化以及VSC控制策略等内容,并展示了仿真实验结果,表明该方案相比传统方法提高了可再生能源利用率和电网稳定性。 适用人群:从事新能源发电系统研究与开发的技术人员,尤其是关注风光储联合并网系统及其控制策略的研究者。 使用场景及目标:适用于需要提高风光储联合并网系统效率和稳定性的场合,特别是在应对复杂气象条件下确保关键负荷持续供电方面具有显著优势。目标是通过引入先进的控制算法和技术手段,优化能源管理和分配机制。 其他说明:文中提供了大量具体的Matlab/Simulink代码片段,帮助读者更好地理解和复现实验过程。此外,还讨论了一些实际应用中的常见问题及解决方案,如锁相环参数调整、风机MPPT策略优化等。

    MedAgent-Pro:通过基于推理的代理工作流实现证据驱动的多模态医学诊断

    开发可靠的AI系统以协助人类临床医生进行多模态医学诊断一直是研究人员的主要目标。近年来,多模态大语言模型(MLLMs)受到了广泛关注,并在多个领域取得了成功。凭借强大的推理能力和根据用户指令执行多种任务的能力,它们在提升医学诊断方面具有巨大潜力。然而,直接将MLLMs应用于医学领域仍面临挑战。它们缺乏对视觉输入的详细感知能力,限制了其进行定量图像分析的能力,而这是医学诊断的关键。此外,MLLMs通常表现出幻觉和推理不一致的问题,而临床诊断必须严格遵循既定标准。为解决这些问题,我们提出了MedAgent-Pro,一个基于证据推理的代理系统,旨在实现可靠、可解释且精确的医学诊断。这通过分层工作流实现:在任务级别上,基于检索到的临床标准的知识推理生成针对特定疾病的可靠诊断计划;而在案例级别上,多个工具代理处理多模态输入,根据计划分析不同指标,并结合定量和定性证据提供最终诊断。在2D和3D医学诊断任务上的综合实验展示了MedAgent-Pro的优越性和有效性,而案例研究进一步突显了其可靠性和可解释性。代码可在以下链接获取: https://github.com/jinlab-imvr/MedA

    西门子S7-1200 PLC三轴伺服控制系统:结构化编程与多模式控制应用

    内容概要:本文详细介绍了基于西门子S7-1200 PLC的三轴伺服控制系统的设计与实现。主要内容涵盖使用UDT(用户自定义数据类型)、多重背景数据块、状态机模式切换以及报警处理等方面。通过结构化编程的方法,实现了代码的高复用性和良好的扩展性。文中还分享了一些具体的编程技巧,如脉冲输出、加减速曲线设置、IO映射等,并讨论了调试过程中遇到的问题及其解决方案。 适合人群:具有一定PLC编程经验的自动化工程师和技术人员。 使用场景及目标:适用于需要进行复杂机电一体化系统集成的工业环境,旨在提高生产效率和维护便捷性。具体应用场景包括但不限于流水线改造、机器人控制等领域。 其他说明:作者强调了结构化编程对于减少冗余代码、提升开发效率的重要性,并指出合理的数据库规划有助于快速定位问题并优化性能。此外,文章还提到了一些实用的小技巧,如利用状态机实现模式切换、采用事件队列管理报警信息等。

    若干 MATLAB 脚本, 函数. 包括一些数学建模算法的应用, 可视化, 和实用的脚本.zip

    matlab

    在线教育系统.zip

    Java项目基于Springboot框架的课程设计,包含LW+ppt

    基于三菱PLC与组态王的恒压供水系统设计及其实现

    内容概要:本文详细介绍了利用三菱PLC(FX5U/FX3U系列)和组态王构建恒压供水系统的全过程。首先阐述了硬件选型与连接方式,包括PLC、变频器、压力传感器等设备的选择与配置。接着深入探讨了PLC内部梯形图编程技巧,特别是PID控制算法的应用,以及如何通过合理的参数整定确保系统的稳定性和响应速度。随后讲解了组态王作为上位机软件的设计要点,强调了动态图形展示、报警机制和历史数据记录等功能的重要性和实现方法。最后分享了一些常见的调试经验和故障排除技巧。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程和HMI开发有一定基础的学习者。 使用场景及目标:适用于新建或改造恒压供水项目的规划与实施,旨在帮助技术人员掌握完整的系统集成流程,提高项目成功率并优化运维效率。 其他说明:文中提供了大量实际案例和代码片段供读者参考,有助于加深理解和快速上手实践。

    C++栈操作的基本概念、操作方法、示例代码以及实际应用场景

    入栈和出栈的基本操作这个文档包含了C++栈操作的基本概念、操作方法、示例代码以及实际应用场景。文档结构清晰,从基础概念到实际应用逐步深入,并提供了练习建议帮助巩固学习

    混合鲸鱼优化算法及其在移动边缘计算系统中的应用.zip

    matlab

    2023年江苏省高等职业院校技能大赛大数据技术与应用赛项竞赛规程.docx

    2023年江苏省高等职业院校技能大赛大数据技术与应用赛项竞赛规程.docx

    《基于yolov8的违章停车检测项目》(包含源码、完整数据集、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是均来自个人的课程设计、毕业设计或者具体项目,代码都测试ok,都是运行成功后才上传资源,答辩评审绝对信服的,拿来就能用。放心下载使用!源码、数据集、部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.dataset.txt文件,仅供学习参考, 切勿用于商业用途。 4、如有侵权请私信博主,感谢支持

    Java SpringBoot构建多用户B2B2C全平台商城系统的架构解析与实战技巧

    内容概要:本文详细介绍了使用Java SpringBoot搭建一个多用户B2B2C商城系统的技术实现。该系统覆盖PC、H5、小程序和APP四个终端,采用SpringBoot作为后端框架,Vue和Uniapp分别用于PC/H5端和移动端的前端开发。文章重点探讨了用户鉴权、商品管理、支付集成、权限控制等多个关键技术点,并分享了许多实际开发过程中积累的经验教训和技术优化方法。例如,通过自定义AccessDecisionManager实现复杂的权限控制,利用Redisson进行分布式锁管理以应对高并发场景,以及运用策略模式封装多种支付渠道等。 适合人群:具有一定Java开发经验和对前后端分离架构有一定了解的研发人员,尤其是关注电商平台开发的技术爱好者。 使用场景及目标:适用于希望深入了解大型电子商务平台内部运作机制的人群;旨在帮助开发者掌握如何高效地构建稳定可靠的多用户商城系统,提高开发效率并降低维护成本。 其他说明:文中不仅提供了详细的代码片段展示各个功能模块的具体实现方式,还特别强调了一些容易忽视但在实际应用中至关重要的细节问题,如跨端适配、性能优化等方面的内容。

    COMSOL中三维离散裂隙注浆模型:基于粘度空间衰减的多组裂隙建模及应用

    内容概要:本文详细介绍了如何利用COMSOL进行三维离散裂隙注浆模型的构建,特别是针对粘度随扩散距离衰减的特点进行了深入探讨。首先,通过COMSOL自带的裂隙网络生成器或自定义脚本创建随机分布或多组定向裂隙网络。然后,定义了考虑空间和时间因素的粘度衰减模型,确保浆液在裂隙内的流动更加符合实际情况。此外,文中还讨论了边界条件的设置技巧,如采用渐进加载方式避免数值不稳定。最后,强调了结果可视化的多种方法,如切片图、流线图以及粒子追踪等功能的应用,帮助更好地理解和展示模拟结果。 适合人群:从事岩土工程、地质勘探及相关领域的科研人员和技术工程师。 使用场景及目标:适用于研究复杂地质条件下裂隙网络中浆液的流动行为,优化注浆施工方案,提高工程安全性和效率。 其他说明:文中提供了大量具体的代码片段和操作步骤,便于读者动手实践并加深理解。同时,通过实例展示了如何将理论模型应用于实际工程项目中,验证了模型的有效性和实用性。

Global site tag (gtag.js) - Google Analytics