java内部类, 我在看《thinking in java》的时候总感觉模棱两可的, 挣扎了好几天之后, 感觉有一部分的问题想的清楚了, 写一个随笔记录一下, 以备以后修改和查看

什么是内部类?

  内部类说白了就是类套类, 在一个类里面写一个类, 内部类分为两种, 一种是普通内部类(non-static nested class), 第二种是静态内部类(static nested class),也叫嵌套类.

  普通内部类包含另外两种特殊的内部类, 一种是局部内部类, 另一种是匿名内部类.

内部类有什么作用?

  1. 最简单的功能 : 一种有效的代码隐藏机制, 将某些功能放置在一起组合形成一个新的类, 而且这个新类可以任意访问类的所有成员. 有效地提高了代码的封装型性, 使写出来的代码更加便于理解
  2. 实现了类逻辑上的分组: 比如 一个类A仅仅只对类B有用处, A是B的辅助类, 或者说仅希望A对B起作用, 那么在逻辑上A已经属于了B类, 内部类就恰好实现了这个逻辑
  3. 和interface一起真正实现了多重继承 : 因为一个类允许存在多个内部类, 而内部类可以随意访问类的所有成员, 那么就可以通过在不同的内部类继承不同的类, 实现不同的接口在真正意义上完成多重继承的任务.
  4. 通过内部类提供闭包的功能, 或者说模拟闭包的功能(这部分暂时没有完全弄明白)

什么是闭包?

  《thinking in java》有一段原话感觉很贴切:

闭包(closure)是一个可调用的对象, 这个对象记录着一些信息, 这些信息来自于创建他的作用域.

通过回调, 对象可以携带一些信息, 这些信息允许它在将来某个时刻调用初始的对象.

内部类就是面向对象的闭包, 创建一个内部类, 就会得到一个外部类的引用, 通过这个引用, 我们可以调用外部类对象的所有成员, 当然这些成员就是所谓的“创建他的域的信息”。除此之外,使用内部类完成闭包更加安全,因为返回的是一个引用,而不是一个指针,指针和引用可操作的权限差异不止一点点。

为什么普通内部类中不能包含static方法、static字段和嵌套类?

  因为static所修饰的属性、方法都是和类相关,而非类对象相关。static成员的访问可以直接通过classname.staticField进行,而内部类的创建是和外部类相关联的,也就是要使用内部类,必须创建一个相关的外部类以提供引用,如果允许static成员的存在,那么就可以通过Outer.Inner.staticField进行访问,与是否存在外部类无关,所以不允许包含static成员。

  但是普通内部类却可以包含static final类型的成员, 因为static final类型的成员是静态常量,在编译期就会将所有用到该成员的地方替换成相对应的子面值常量。所以static final类型的成员只能使用常量表达式进行初始化。

例如:

class SS {
public class Test1
{
public static final String str ="";
public static final Integer d = new Integer(25) ; //报错:The field d cannot be declared static in a non-static inner type, unless initialized with a constant expression
}
}

为什么局部内部类访问的局部变量必须是final类型?

  什么是局部内部类?

    局部内部类是一种特殊的内部类, 只能被定义在代码段Block中 ,也就是由"{"和"}"围成的作用域中. 比如一个代码块中, 一个方法中,一个for循环中,甚至是一个if(){...}中

    局部内部类只能在它定义的代码段中被访问,外界是无法访问到的, 所以在外界定义一个相同名字的类,甚至是interface

    定义在静态方法中的局部内部类只能访问外部类的静态成员, 而定义在普通方法中的则没有限制.

public class OutClass
{
private int a = 0 ;
private static int b = 1 ; public static void c1()
{
class InClass
{
{
System.out.println(a); //由于这个内部类是定义在静态方法中的,所以只能访问外部类的静态成员,所以这行会报错
System.out.println(b) ;
}
}
} public void c2()
{
//完全正确
class InClass
{
{
System.out.println(a) ;
System.out.println(b) ;
}
}
} public class InClass
{ }
} class InClass
{ }

  当局部内部类访问局部变量或形参时时, 这些变量和参数必须是final类型, 如果你的JDK是java8的话, 形参和变量允许是effectively final类型, 所谓effectively final类型就是虽然声明时没有声明成final类型, 但是他的值(基本数据类型)或引用(引用数据类型)从来没有改变过.(估计是java8做了一些优化吧,太深奥的就不懂了)

  局部类使用局部变量和参数之所以必须是final类型的, 和他们的生命周期有关. 局部类是一个类, 他的生命周期和外部类是一样的, 而局部变量和参数则不同, 一旦退出了他们所在的代码段, 就会被销毁, 如果允许一个内部类持有一个这样的变量或者说成员, 是十分不安全的, 所以为了“延续”这些局部变量和参数的生命周期(毕竟不是真正的延续), 所采取的办法就是将他们复制一份, 也就是基本数据类型拷贝一份, 引用数据类型拷贝引用. 那么如何保证内外一致呢?就必须将他们定义成final类型.

//Local classes : http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html

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

//有关于final的解释: http://bbs.csdn.net/topics/300068105 , http://blog.csdn.net/onisland/article/details/5807637

//Java中普通内部类为何不能有static数据和static字段,也不能包含嵌套类 :http://www.dewen.io/q/13793

//thinking in java笔记,如果有不对的地方,还望指正^_^

java内部类的一些看法的更多相关文章

  1. Java内部类final语义实现

    本文描述在java内部类中,经常会引用外部类的变量信息.但是这些变量信息是如何传递给内部类的,在表面上并没有相应的线索.本文从字节码层描述在内部类中是如何实现这些语义的. 本地临时变量 基本类型 fi ...

  2. Java内部类详解

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  3. 黑马----JAVA内部类

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 黑马程序员--JAVA内部类 一.内部类分为显式内部类和匿名内部类. 二.显式内部类 1.即显式声明的内部类,它有类名. 2.显 ...

  4. java 内部类 *** 最爱那水货

    注: 转载于http://blog.csdn.net/jiangxinyu/article/details/8177326 Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类.内部类又 ...

  5. java内部类和匿名内部类

    内部类即是包含在类里面的又一个类. java内部类分为: 成员内部类.静态嵌套类.方法内部类.匿名内部类 . 内部类的共性 (1).内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.clas ...

  6. Java内部类小程序(成员内部类,静态内部类,匿名内部类)

    /** * 测试java内部类(成员内部类,静态内部类,匿名内部类) * 局部内部类不常用,就不写了. * @package :java05 * @author shaobn * @Describe ...

  7. [转] Java内部类详解

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

  8. java内部类的作用分析

    提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比.内部类从表面上看,就 ...

  9. 9)Java内部类(Inner Class)

      内部类:不可以有静态数据,静态方法或者又一个静态内部类      内部类的优点:隐藏类的细节,内部类可以声明为私有.内部类可以访问外部类的对象(包括private) 静态内部类:可以有静态数据,静 ...

随机推荐

  1. 九度oj题目1009:二叉搜索树

    题目描述: 判断两序列是否为同一二叉搜索树序列 输入:                        开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接 ...

  2. 也来“玩”Metro UI之磁贴(二)

    继昨天的“也来“玩”Metro UI之磁贴(一)”之后,还不过瘾,今天继续“玩”吧——今天把单选的功能加进来,还有磁贴的内容,还加了发光效果(CSS3,IE9+浏览器),当然,还是纯CSS,真的要感谢 ...

  3. mysqlbinlog备份和mysqldump备份

    -bash : mysqldump: command not found -bash : mysqlbinlog:command not found 首先得知道mysql命令或mysqldump命令的 ...

  4. RHEL7网卡命名规则

    systemd 和 udev 引入了一种新的网络设备命名方式:一致网络设备命名(CONSISTENT NETWORK DEVICE NAMING).根据固件.拓扑.位置信息来设置固定名字,带来的好处是 ...

  5. iOS转场动画初探

    一般我们就用两种转场push和present present /** 1.设置代理 - (instancetype)init { self = [super init]; if (self) { se ...

  6. BZOJ 3230 相似子串 ——后缀数组

    题目的Source好有趣. 我们求出SA,然后求出每一个后缀中与前面本质不同的字符串的个数. 然后二分求出当前的字符串. 然后就是正反两次后缀数组求LCP的裸题了. 要注意,这时两个串的起点可能会相同 ...

  7. BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...

  8. POJ2096 Collecting Bugs(概率DP,求期望)

    Collecting Bugs Ivan is fond of collecting. Unlike other people who collect post stamps, coins or ot ...

  9. LVM 类型的 Storage Pool

    LVM 类型的 Storage Pool 不仅一个文件可以分配给客户机作为虚拟磁盘,宿主机上 VG 中的 LV 也可以作为虚拟磁盘分配给虚拟机使用. 不过,LV 由于没有磁盘的 MBR 引导记录,不能 ...

  10. 如何让Gridview在没有数据的时候显示表头[没有使用SqlDataSource控件时]

    原文发布时间为:2008-08-03 -- 来源于本人的百度文章 [由搬家工具导入] 要看全文请点击http://blog.csdn.net/windok2004/archive/2007/10/28 ...