java(6)内部类基础

转载 2015年11月18日 23:10:23

【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java内部类 的基础知识;


【1】内部类相关

1.1)为什么要使用 内部类?(Reason)

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

1.2)嵌套类有两个好处(Merit):

  • M1)命名控制+访问控制;
  • M2)需要注意的是, Link类位于 LinkedList 类 的私有部分, 因此,Link对其他的代码均不可见;鉴于此情况,可以将Link的数据域设计为 public, 它仍然是安全的,因为这些数据域只能被 LinkedList类中的方法访问, 而不会暴露给其他的代码;

【2】使用内部类访问对象状态

2.1)看个荔枝:构造一个语音时钟需要两个参数:发布通告的时间间隔 + 开关铃声的标志:
这里写图片描述
2.2)需要注意: 这里的 TimePrinter 位于 TalkingClock 的内部, 并不意味着 每个 TalkingClock 都有一个 TimePrinter 实例域;
2.3)看更加详细的 TimePrinter(值得注意的是,actionPerformed 方法在发出铃声前检查了 beep 标志):
这里写图片描述
这是因为, 内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域(干货);
2.4)为了能够运行这个程序, 内部类的对象有一个隐式引用, 它指向了 创建它的外部类对象(内部类对象拥有一个对外围类对象 的 引用):
这里写图片描述
2.5)外围类的引用在构造器中设置。编译器修改了所有的内部类的构造器, 添加了一个外围类引用的参数, 因为 TimePrinter 类没有定义构造器, 所以编译器为这个类生成了一个默认构造器;
2.6)当在 start方法中创建了 TimerPrinter对象后, 编译器就会将 this 引用传递给当前的语音时钟构造器:

ActionListener listener = new TimePrinter(this);   // parameter automatically added

Annotation) TimerPrinter 类声明为私有的, 这样一来, 只有 TalkingClock的方法才能够构造 TimePrinter对象, 只有内部类可以是私有类,而常规类只可以具有包可见性, 或公有可见性;

package com.corejava.chapter6_2;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

/**
 * This program demonstrates the use of inner classes.
 * @version 1.10 2004-02-27
 * @author Cay Horstmann
 */
public class InnerClassTest
{
   public static void main(String[] args)
   {
      TalkingClock clock = new TalkingClock(1000, true);
      clock.start();

      // keep program running until user selects "Ok"
      JOptionPane.showMessageDialog(null, "Quit program?");
      System.exit(0);
   }
}

/**
 * A clock that prints the time in regular intervals.
 */
class TalkingClock
{
   private int interval;
   private boolean beep;

   /**
    * Constructs a talking clock
    * @param interval the interval between messages (in milliseconds)
    * @param beep true if the clock should beep
    */
   public TalkingClock(int interval, boolean beep)
   {
      this.interval = interval;
      this.beep = beep;
   }

   /**
    * Starts the clock.
    */
   public void start()
   {
      ActionListener listener = new TimePrinter();
      Timer t = new Timer(interval, listener);
      t.start();
   }

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

这里写图片描述


【3】内部类的特殊语法规则

3.1)使用外围类引用的正规语法还要复杂一些, 表达式 OuterClass.this 表示外围类的引用;如:

public void actionPerformed(ActionEvent event)
{
    if(TalkingClock.this.beep) Tookit.getDefaultToolkit().beep();
}
  • 反过来,可以采用下列语法格式更加明确地编写内部对象的构造器:(下面代码中的this是外部类调用start方法的时候,传了一个外部类本身的this引用,this.new == TalkingClock.new TimePrinter)
outerObject.new InnerClass(construction parameters)
 如,  ActionListener listener = this.new TimePrinter();
  • 上面的代码中: 最新构造的 TimePrinter 对象 的外围类引用被设置为创建内部类对象的方法中的this引用;这是一种最常见的 情况;

3.2)可以显式地命名将外围类引用设置为其他的对象:如, 如果TimerPrinter 是一个公有内部类,对于任意的语音时钟都可以构造一个 TimePrinter:

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

Attention)需要注意, 在外部类的作用域之外,可以这样引用内部类:

OuterClass.InnerClass

【4】内部类是否有用、必要和安全

4.1)内部类是一种编译器现象, 与虚拟机无关:编译器将会把内部类翻译为用 $ 分隔外部类名和内部类名的常规类文件, 而虚拟机则对此一无所知;
如, 在 TalkingClock 类内部的 TimePrinter 类将被翻译成类文件 TalkingClock\$TimePrinter.class;
4.2)可以看到: 编译器为了引用外围类,生成了一个附加的实例域 this$0;
4.3)内部类可以访问外围类的私有数据, 而常规类则不行:可见, 由于内部类拥有访问特权, 所以与常规类比较起来功能更加强大;
这里写图片描述

Java基础[6]-4-内部类

内部类内部类在一个类中存在的其他类,叫做内部类。内部类作用 内部类可以很好的实现隐藏,对同一个包中的其他类不可见。一般的非内部类,是不允许有 private 与protected权限的,但内部类可以。...
  • BiLaHePan
  • BiLaHePan
  • 2017年07月23日 17:04
  • 477

Java 创建内部类实例

编程中需要访问内部类,写C习惯了Java方式多少有些生硬。 其实很简单: 1 拥有内部类的一个类 public class B{ public void showData() { ...
  • xiaoleiacm
  • xiaoleiacm
  • 2016年03月01日 15:28
  • 2816

java内部类常见面试题汇总

1.根据注释填写(1),(2),(3)处的代码 public class Test{ public static void main(String[] args){ /...
  • tomcat_2014
  • tomcat_2014
  • 2016年04月18日 17:13
  • 2824

java内部类的四大作用

放在一个类的内部的类我们就叫内部类。 二、 作用 1.内部类可以很好的实现隐藏  一般的非内部类,是不允许有 private 与protected权限的,但内部类可以 2.内部类拥有外围类的所...
  • mid120
  • mid120
  • 2016年12月14日 19:25
  • 3495

java 四种内部类 使用细节(含代码)

一: 内部类     定义在类体部,方法体部,甚至比方法体更小的代码块内部的类(if 语句里面等)     1.静态内部类(内部类中最简单的形式)         1.声明在类体部,方法体外,并...
  • qq_33599978
  • qq_33599978
  • 2017年04月27日 23:28
  • 511

JAVA和C++内部类

JAVA和C++内部类的异同
  • qq78442761
  • qq78442761
  • 2016年11月21日 22:52
  • 477

java内部类解析及应用场景简介

转自:http://blog.csdn.net/historyasamirror/article/details/6049073 所谓内部类,就是一个类的定义放在了另一个类定义的内部,如: ...
  • oliveevilo
  • oliveevilo
  • 2012年07月13日 17:23
  • 1756

java中的内部类完全总结

一.内部类基础   在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。下面就...
  • pangqiandou
  • pangqiandou
  • 2016年11月19日 21:57
  • 1823

Java 四种内部类

Java 内部类  分四种:成员内部类、局部内部类、静态内部类和匿名内部类。  1、成员内部类: 即作为外部类的一个成员存在,与外部类的属性、方法并列。 注意:成员内部类中不能定义静态变量,但可以访问...
  • superit401
  • superit401
  • 2016年07月30日 18:01
  • 4899

最安全的单例模式--java使用内部类实现单例模式

实现类 public class Singleton {     private static class LazyHolder {            private static fina...
  • qq_22912803
  • qq_22912803
  • 2016年10月10日 12:57
  • 5375
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java(6)内部类基础
举报原因:
原因补充:

(最多只允许输入30个字)