引言

内部类,嵌套在另一个类的里面,所以也称为 嵌套类;

内部类分为以下四种:

  • 静态内部类
  • 成员内部类
  • 局部内部类
  • 匿名内部类

一、静态内部类

静态内部类: 一般也称”静态嵌套类“,在类中用static声明的内部类。

因为是static,所以不依赖于外围类对象实例而独立存在,静态内部类的可以访问外围类中的所有静态成员,包括private的静态成员

同时静态内部类可以说是所有内部类中独立性最高的内部类,其创建对象、继承(实现接口)、扩展子类等使用方式与外围类并没有多大的区别。

public class OuterClass {//外围类public int aa; //实例成员private static float f = 1.5f;//private的静态成员static void println() {System.out.println("这是静态方法");}protected static class StaticInnerClass{//protected的静态内部类float a;public StaticInnerClass() {a = f;// 外围类的private静态变量println();//外围类的静态方法}}
}class OtherClass{public static void main(String[] args) {//创建静态内部类的对象OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass(); }
}

二、成员内部类

成员内部类: 定义在类的内部,而且与成员方法、成员变量同级,即也是外围类的成员之一,因此 成员内部类 与 外围类 是紧密关联的。

注意:
这种紧密关联指的是,成员内部类的对象的创建必须依赖于外围类的对象(即没有外围类对象,就不可能创建成员内部类)。因此,成员内部类有以下3个特点:

  • 成员内部类可以访问外围类的所有成员,包括私有成员;
  • 成员内部类是不可以声明静态成员(包括静态变量、静态方法、静态成员类、嵌套接口),但有个例外—可以声明 static final的变量, 这是因为编译器对final类型的特殊处理,是直接将值写入字节码;
  • 成员内部类对象都隐式地保存了一个引用,指向创建它的外部类对象;或者说,成员内部类的入口是由外围类的对象保持着(静态内部类的入口,则直接由外围类保持着)

成员内部类中的 this,new关键字:
- 获取外部类对象:OuterClass.this
- 明确指定使用外部类的成员(当内部类与外部类的名字冲突时):
OuterClass.this.成员名
- 创建内部类对象的new:外围类对象.new

//先创建外围类对象
OuterClass outer=new OuterClass();
//创建成员内部类对象
OuterClass.InnerClass inner=outer.new InnerClass();

1. 成员内部类的对象创建

  我们知道,成员内部类就像外围类的实例成员一样,一定要存在对象才能访问,即成员内部类必须绑定一个外围类的对象。上面已经介绍了成员内部类的创建格式了,我们直接看一个例子

public class OuterClass {//外围类public int aa; //实例成员private static float f = 1.5f;//private的静态成员public void initInnerClass() {System.out.println("内部类的初始化方法");}public void createInnerClass() {////外围类的成员方法中创建成员内部类对象InnerClass innerClass = new InnerClass();}class InnerClass{//成员内部类private double aa; //与围类的变量aa的名字重复public InnerClass(){this.aa = OuterClass.this.aa + f;//明确指定两个aa的所属initInnerClass();}}
}//其他类
class OtherClass{public static void main(String[] args) {//其他类中创建成员内部类OuterClass oc = new OuterClass();//外部类对象//创建内部类对象OuterClass.InnerClass innerClass = oc.new InnerClass();}
}

  注意上面的例子中,在外围类的成员方法中创建成员内部类 与 在其他类中或静态方法中创建成员内部的方式是不一样的。

补充几点:

  • 成员内部类可以继续包含成员内部类,而且不管一个内部类被嵌套了多少层,它都能透明地访问它的所有外部类所有成员;
  • 成员内部可以继续嵌套多层的成员内部类,但无法嵌套静态内部类;静态内部类则都可以继续嵌套这两种内部类。

下面的例子是基于上面的例子进行改造:

class InnerClass{//成员内部类private double aa; //与围类的变量aa的名字重复public InnerClass(){this.aa = OuterClass.this.aa + f;//明确指定两个aa的所属initInnerClass();}public  class InnerInnerCalss2{//成员内部类中的成员内部类protected double aa = OuterClass.this.aa;//最外层的外围类的成员变量}//InnerInnerCalss2}//InnerClass

2. 继承成员内部类

在内部类的访问权限允许的情况下,成员内部类也是可以被继承的。由于成员内部类的对象依赖于外围类的对象,或者说,成员内部类的构造器入口由外围类的对象把持着。因此,继承了成员内部类的子类必须要与一个外围类对象关联起来。同时,子类的构造器是必须要调用父类的构造器方法,所以也只能通过父类的外围类对象来调用父类构造器。

下面的例子也是基于上面的例子的,只贴出多出的部分代码。

class ChildClass extends OuterClass.InnerClass{//成员内部类的子类的构造器的格式public ChildClass(OuterClass outerClass) {outerClass.super();//通过外围类的对象调用父类的构造方法}
}

三、局部内部类

局部内部类: 就是在方法、构造器、初始化块中声明的类,在结构上类似于一个局部变量。因此局部内部类是不能使用访问修饰符

局部内部类的两个访问限制

  • 对于局部变量,局部内部类只能访问final的局部变量。不过,后期JDK(忘了是JDK几了)局部变量可不用final修饰,也可以被局部内部类访问,但你必须时刻记住此局部变量已经是final了,不能再改变。
  • 对于类的全局成员,局部内部类定义在实例环境中(构造器、对象成员方法、实例初始化块),则可以访问外围类的所有成员;但如果内部类定义在静态环境中(静态初始化块、静态方法),则只能访问外围类的静态成员。
public class OuterClass {private int a = 21;static {//静态域中的局部内部类class LocalClass1{//  int z = a; //错误,在静态的作用域中无法访问对象成员}}{//实例初始化块中的局部内部类class localClass2{          }}public OuterClass(){int x = 2;final int y = 3;// x = 3;//若放开此行注释,编译无法通过,因为局部变量x已经是final类型//构造器中的局部内部类class localClass3{int z = y; //可以访问final的局部变量int b = a;//可以访问类的所有成员//访问没有用final修饰的局部变量int c = x;}}public void createRunnable() {final int x = 4;//方法中的局部内部类class LocalClass4 implements Runnable {//@Overridepublic void run() {System.out.println("局部final变量:"+x);System.out.println("对象成员变量:"+a);}}}
}

四、匿名内部类

匿名内部类: 与局部内部类很相似,只不过匿名内部类是一个没有给定名字的内部类,在创建这个匿名内部类后,便会立即用来创建并返回此内部类的一个对象引用。

作用:匿名内部类用于隐式继承某个类(重写里面的方法或实现抽象方法)或者实现某个接口。

匿名内部类的访问限制: 与局部内部类一样,请参考局部内部类;

匿名内部类的优缺点:
优点: 编码方便快捷;
缺点:

  • 只能继承一个类或实现一个接口,不能再继承其他类或其他接口。
  • 只能用于创建一次对象实例;

下面的例子是我们创建线程时经常用到的匿名内部类的方式来快速地创建一个对象的例子:

 class MyOuterClass {private int x = 5;void createThread() {final int a = 10;int b = 189;// 匿名内部类继承Thread类,并重写Run方法Thread thread = new Thread("thread-1") {int c = x;  //访问成员变量int d = a;  //final的局部变量int e = b; //访问没有用final修饰的局部变量@Overridepublic void run() {System.out.println("这是线程thread-1");}};// 匿名内部类实现Runnable接口Runnable r = new Runnable() {@Overridepublic void run() {System.out.println("线程运行中");}};}
}

总结

类 型 访问修饰符 声明静态成员 绑定外围类
静态内部类 四种访问修饰符 可以声明 不绑定
成员内部类 四种访问修饰符 除 final static 的变量外,其余静态成员都不行 绑定
局部内部类 不可以声明 不可以声明 取决于此内部类的声明环境
匿名内部类 不可以声明 不可以声明 取决于此内部类的声明环境

作者:jinggod
出处:http://www.cnblogs.com/jinggod/p/8503143.html

类与接口(二)java的四种内部类详解相关推荐

  1. 内部类(四种内部类详解)

    == = = = = = = 内部类(四种内部类详解)= = = = = = = == 一.基本介绍:一个类的内部又完整的嵌套了另一个类结构.被嵌套的类称为内部类(inner class),嵌套其他类 ...

  2. 四种内部类详解【内含详细例子】【保姆级教程】

    内部类 类里面:成员内部类 ,静态内部类(区别就是是否有static) 方法里面:匿名内部类,局部内部类(匿名内部类没有类名,局部内部类有) ok 学到这里,类的五大组成部分就出来了:属性,构造器,方 ...

  3. java正则表达式判断问号_正则表达式问号的四种用法详解

    原文符号 因为?在正则表达式中有特殊的含义,所以如果想匹配?本身,则需要转义,\? 有无量词 问号可以表示重复前面内容的0次或一次,也就是要么不出现,要么出现一次. 非贪婪匹配 贪婪匹配 在满足匹配时 ...

  4. js和php能生成一样的随机数_JavaScript_JS生成某个范围的随机数【四种情况详解】,前言: JS没有现成的函数,能 - phpStudy...

    JS生成某个范围的随机数[四种情况详解] 前言: JS没有现成的函数,能够直接生成指定范围的随机数. 但是它有个函数:Math.random()  这个函数可以生成 [0,1) 的一个随机数. 利用它 ...

  5. RTSP、HTTP、HTTPS、SDP四种协议详解

    RTSP.HTTP.HTTPS.SDP四种协议详解 从这篇开始我们将进入流媒体的环节,流媒体在android中有nuplayer来实现的,在开始讲解android流媒体前,我们先来讲讲流媒体传输协议, ...

  6. kinux查日志_Linux实时查看日志的四种命令详解

    原标题:Linux实时查看日志的四种命令详解 如何在Linux中实时查看日志文件的内容?那么有很多实用程序可以帮助用户在文件更改或不断更新时输出文件的内容.在Linux中实时显示文件内容的常用命令是t ...

  7. python输入字符串并反序result_python字符串反转的四种方法详解

    python字符串反转的四种方法详解 这篇文章主要介绍了python字符串反转的四种详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.用red ...

  8. php 去重_php求两数组交集的四种方法详解

    题目:给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1],nums2 = [2,2] 输出: [2] 示例 2: 输入: nums1 = [4,9,5 ...

  9. WebSocket四种事件详解 入门篇(二)

    示例代码  在文章最下方,可以根据示例代码和讲解来理解整个WebSocket流程.代码用SpringBoot 和 maven搭建 服务端和客户端四种事件 1.打开事件 此事件发生在端点上建立新连接时并 ...

最新文章

  1. wdcp php5.3 pdo_mysql,WDCP常用组件(memcache、mysqli、PDO_MYSQL、mysql innodb、libmcrypt、php zip)的安装方法...
  2. python里面的pip是什么意思_Python-pip和conda有什么区别?
  3. [CQOI2012] 局部极小值(状压DP + 容斥 + 搜索)
  4. 共享充电宝还在打仗,支付宝已经笑了
  5. H5商城在微信APP里支付
  6. Data URL 基本介绍
  7. 使用ArcPy将nc格式数据转换为tif格式数据
  8. Intellij IDEA如何打包jar文件?
  9. matlab电路图powergui怎么用,使用matlab中的powergui对采集的数据进行谐波分析#实验日记#...
  10. Java中使用Protocol Buffer
  11. mongodb一致性协议_Mongodb选举机制
  12. Win7怎么打开磁盘管理?
  13. NLP与对比学习的巧妙融合,简单暴力效果显著!
  14. 啤酒与尿布:数据分析相关性分析案例一
  15. 用久的苹果电脑是闲置回收还是维修
  16. jenkins 流水线参数化构建例子
  17. 图片格式怎么转换?推荐三种实用的转换方法
  18. pyqt5代码实例2
  19. 二维码教程之如何制作表白二维码
  20. SSM巢湖学院校园报修系统毕业设计源码021813

热门文章

  1. 为什么要重映射那个GPIO_Remap_SWJ_JTAGDisable
  2. 趣链 BitXHub跨链平台 (1)技术架构
  3. 初等数论--整除--两数乘积保持整除性
  4. 近世代数--内直积--内直积是什么?充要条件?
  5. 攻防世界第四题Reverse re1
  6. 【django】查询集QuerySet
  7. [armv9]-Introducing-Arm-Confidential-Compute-Architecture
  8. [答疑]-ATF中异常向量表为何没有实现“Current Exception level with SP_ELx, x>0.“
  9. 计算机英语翻译的典故,中国成语典故英语翻译大全
  10. Win32 Edit 文本框追加字符串