以前看<Java编程思想>的时候,看到过嵌套类跟内部类的区别,不过后来就把它们的概念给忘了吧。昨天在看<数据结构与算法分析(Java语言版)>的时候,又遇到了这个概念,当时就很大的疑惑:嵌套类跟内部类有什么区别?只有是否有关键字static的区别吗?

所以今天找了个时间查了一下两者的详细区别,总结在这篇博客中,既方便自己的复习和学习,也启示他人吧。

1,概念:

定义在一个类内部的类,叫作“嵌套类”。嵌套类分为两种:static的和非static的。后者又有一个专门的名字,叫作“内部类”。所以从概念可以看出,嵌套类跟内部类是所属关系,后者包含于前者。示例代码如下:

 class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}

同时,嵌套类是其所在类的成员。内部类可以访问所在类的所有成员,即使该成员是private的。而static嵌套类则不得访问所在类的成员。同时,嵌套类,static和非static的,都可以被声明为private、public、protected和default的。

2,为什么要使用嵌套类?

好处应该都比较文本化吧,以后在使用的过程中去理解和体会吧:对只在一个地方使用的类进行逻辑上的分组;增加了封装性;易于阅读和维护。

3,static嵌套类:

因为static嵌套类不能直接访问所在类的非static成员变量和方法,所以static嵌套类必须通过绑定所在类的实例来进行访问。而对于所在类的静态成员和方法包括private、protected和public的,可以访问。因为它也有static修饰。

static嵌套类通过写出封装的类名来进行实例化和访问其内部成员:

 OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();

4,内部类:

因为内部类是所在类的成员,所以它可以访问所在类的任意变量和方法,但是它本身却不能定义任何static的变量或方法。

同时,内部类的实例化方式也与static嵌套类有所不同:

 OuterClass outerObject=new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

static嵌套类与non-static嵌套类,在形式上只有是否含有static关键字的区别,但是JVM在初始化时两者还是有差别的:差别就是后者在实例化时会自动地与外围实例建立一种联系,且这种联系不得修改。JVM在实例化non-static嵌套类时会生成一个指向外围实例的对象引用(this),保存这种引用将会消耗时间和空间,同时,在外围实例满足垃圾回收的条件时仍然得以留存。

5,内部类的分类:

以前曾经接触过内部类的分类,这里一并总结一下:

以前的所谓的一些面试宝典里面差不多都是将内部类分为四个种类:

静态内部类(既static嵌套类)、成员内部类(既上述内部类)、局部内部类和匿名内部类。前两者都已经介绍过了,下面专门看一下后面两者。

5.1,局部内部类:

定义在方法内部的类叫作“局部内部类”。它的作用域仅限于方法作用域内,只能在方法的作用域内定义和实例化,是用处最小的类类型。和局部变量一样,它不能被修饰为private, public, protected和static的,并且只能访问方法内部定义的final变量。

 class LocalInner
{
int a = 1; public void doSomething()
{
int b = 2;
final int c = 3;
// 定义一个局部内部类
class Inner3
{
public void test()
{
System.out.println("Hello World");
System.out.println(a); // 不可以访问非final的局部变量
// error: Cannot refer to a non-final variable b inside an inner
// class defined in a different method
// System.out.println(b); // 可以访问final变量
System.out.println(c);
}
} // 创建局部内部类的实例并调用方法
new Inner3().test();
}
} public class LocalInnerClassTest
{
public static void main(String[] args)
{
// 创建外部类对象
LocalInner inner = new LocalInner();
// 调用外部类的方法
inner.doSomething();
} }

5.2,匿名内部类:

顾名思义,匿名内部类就是没有名字的局部类。它不使用关键字class, extends, implements以及构造函数。

它通常作为方法的一个参数传入,比如在android开发中对一个Button添加一个OnClickListener监听器。

匿名内部类隐匿的继承了一个父类或者实现了一个接口。比如:

 mUiHandler.post(new Runnable{
@override
public void run(){
//
} }); AsyncClient.get(url, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers,
JSONObject response) {
// TODO Auto-generated method stub
super.onSuccess(statusCode, headers, response);}} );

内部类通过将相关的类组织在一直,从而降低了命名空间的复杂性。

6,内部类的序列化问题。

对任何种类内部类(包括局部内部类和匿名内部类)的序列化都是不被鼓励的。因为java编译器在对内部类进行编译的时候,将进行“合成构造”。合成构造使得java编译器实现了java的新特性,但是却没有对JVM做出相应的改变。然而,不同的java编译器对合成构造是有差别的,因而,如果对内部类进行了序列化,将使得不同的JRE实现中存在兼容性问题。

本文是在参考了大量他人的劳动成果之上的而写成的,主要的参考文献有:

http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html;

http://www.cnblogs.com/mengdd/archive/2013/02/08/2909307.html。

Java中的嵌套类和内部类的更多相关文章

  1. kotlin中的嵌套类与内部类

    Java中的内部类和静态内部类在Java中内部类简言之就是在一个类的内部定义的另一个类.当然在如果这个内部类被static修饰符修饰,那就是一个静态内部类.关于内部类 和静态内部类除了修饰符的区别之外 ...

  2. python中的嵌套类(内部类调用外部类中的方法函数)

    在为书中版本是3.X的,但2.X不太支持直接调用. 所以,在PYTHON2.X中,要在内部类中调用外部类的方法,就必须得实例化外部类,然后,传入实例进行调用. 花了我两个小时啊,资料没找到,自己一个一 ...

  3. JAVA 嵌套类和内部类

    一.什么是嵌套类及内部类?  可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:  静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套类, ...

  4. 分析java 嵌套类与内部类

    一.什么是嵌套类及内部类?     可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套类 ...

  5. 深入理解java嵌套类和内部类

    一.什么是嵌套类及内部类 能够在一个类的内部定义还有一个类.这样的类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类.静态嵌套类使用非常少,最重要的是非静态嵌套类,也 ...

  6. (十二)java嵌套类和内部类

    嵌套类和内部类:在一个类里边定义的类叫做嵌套类,其中没有static修饰的嵌套类是我们通常说的内部类,而被static修饰的嵌套类不常用.有的地方没有嵌套类和内部类的区分,直接是嵌套类就称作内部类,没 ...

  7. 【java开发系列】—— 嵌套类与内部类

    嵌套类与内部类在java中使用的很广泛,为了避免难以理解,这里用了几个小例子,说明它的用法. 嵌套类与内部类的结构如下图 静态嵌套类 静态嵌套类,是一种在类之外声明的嵌套类,由于是静态的,所以不经过初 ...

  8. spring 笔记1: mvn 中Controller方法的参数不能是嵌套类(内部类)。

    最近做spring开发,个人认为,Controller和客户端js通讯时传递的参数类 只使用某几个方法,为了减少对其他功能的影响,想把参数类定义为Controller类的 嵌套类(内部类).但是实践发 ...

  9. java中普通的顶级类是不能使用static关键字修饰的。只有内部类可以使用static修饰,也可以不使用staitc关键字修饰。

    java中普通的顶级类是不能使用static关键字修饰的.只有内部类可以使用static修饰,也可以不使用staitc关键字修饰. java中的类可以是static吗?答案是可以.在java中我们可以 ...

随机推荐

  1. Ajax跨域请求数据实例(JSOPN方式)

    今天在做取消申请的时候遇到了一个跨域ajax提交的问题. 情景是: 系统A是asp.net的站点,其中包括一个取消申请的接口(get方式通过参数提交到系统的某一个页面,然后返回提交成功或失败) 系统B ...

  2. 最新Oracle 和 mysql 的对比参照----开发篇(转)

    Oracle mysql 对比版本 Release 10.2.0.1.0 XE  windowsXP 5.0.45-community-nt-log MySQL Community Edition ( ...

  3. Swift——(两)Swift访问元组

    在Swift在,获取元组的值到一个位置,通过三种方法: 1.使用元组变量/常量     @Author: twlkyao转载或者引用请保留此行. let http404Error = (404, &q ...

  4. OR1200数据Cache介绍

    以下摘录<步骤吓得核心--软-core处理器的室内设计与分析>一本书 上一章剖析了ICache模块. 本章将剖析DCache模块.首先指出DCache模块相比ICache的特别之处.由于这 ...

  5. codeforces 438D

    在大大推荐下这个标题不明的人做.而我的最后一个非常喜欢的段树,因此,愤怒出手.认为基本上相同.大值,当最大值小于取模时能够剪枝. 今后再遇到此类问题算是能攻克了 // file name: d.cpp ...

  6. I Love This Game 2115(结构体)

    Problem Description Do you like playing basketball ? If you are , you may know the NBA Skills Challe ...

  7. 基于Js实现的UrlEncode和UrlDecode函数代码

    <script language="javascript">//UrlEncode函数function UrlEncode(str){  var ret="& ...

  8. 笔记28 mssql的update :from语法

    原文:笔记28 mssql的update :from语法 笔记28 mssql的update :from语法 --mssql的update :from语法 --a表 b表 结构分别 id ,name ...

  9. PHP的垃圾回收机制详解

    原文:PHP的垃圾回收机制详解 最近由于使用php编写了一个脚本,模拟实现了一个守护进程,因此需要深入理解php中的垃圾回收机制.本文参考了PHP手册. 在理解PHP垃圾回收机制(GC)之前,先了解一 ...

  10. SSAS系列——【03】多维数据(多维数据集对象)

    原文:SSAS系列--[03]多维数据(多维数据集对象) 1.什么是Cube? 简单 Cube 对象由基本信息.维度和度量值组组成. 基本信息包括多维数据集的名称.多维数据集的默认度量值.数据源和存储 ...