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)内部类可以访问外围类的私有数据, 而常规类则不行:可见, 由于内部类拥有访问特权, 所以与常规类比较起来功能更加强大;
这里写图片描述

黑马程序员—6—Java基础:内部类学习笔记和心得体会

------- android培训、java培训、期待与您交流! ---------- 1.      将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。 2.   ...

--面向对象第二部分-内部类、异常--java学习日记6(基础知识)

面向对象是一种思想,它将事物抽象,封装,
  • qq_1991
  • qq_1991
  • 2014年07月17日 00:50
  • 541

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

内部类内部类在一个类中存在的其他类,叫做内部类。内部类作用 内部类可以很好的实现隐藏,对同一个包中的其他类不可见。一般的非内部类,是不允许有 private 与protected权限的,但内部类可以。...

接口、内部类和Java API基础

  • 2011年11月24日 18:53
  • 209KB
  • 下载

java基础四种匿名内部类

  • 2017年08月09日 23:08
  • 42.78MB
  • 下载

【Java编程思想】(6)内部类

1. 如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须具体地指明这个对象的类型:OuterClassName.InnerClassName。 2....
  • scarthr
  • scarthr
  • 2015年06月25日 11:11
  • 388

Java__接口、内部类和Java_API基础

  • 2011年06月11日 21:44
  • 591KB
  • 下载

Java 基础夯实4:内部类的使用场景介绍

文章出自:安卓进阶学习指南主要贡献者: Cloud9527 Alex_赵 Struggle shixinzhang 读完本文你将了解: 通过反编译介...

Java基础 7 类型转换 接口 内部类

标识符是什么? 标识符就是java语言编程中名字。 java命名规则 1,所有的标识符只能包含字母,数字 ,下划线(_),美元符号($); 2, 不能以数字开头 3,...
  • Dome_
  • Dome_
  • 2017年12月08日 08:14
  • 24

黑马程序员 ——Java基础之内部类、异常、包

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 内部类   在类内部可定义成员变量与方法,有趣的是,在类内部也可以定义另一个类。如果在类 ...
  • zdh_61
  • zdh_61
  • 2015年05月15日 18:46
  • 302
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java(6)内部类基础
举报原因:
原因补充:

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