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. Python2.6.6升级2.7.3

    Python2.7替换2.6: 1.下载Python-2.7.3 #wget http://python.org/ftp/python/2.7.3/Python-2.7.3.tar.bz2 2.解压 ...

  2. 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分

    题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...

  3. 【bzoj2989】数列 KD-tree+旋转坐标系

    题目描述 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|. 2种操作(k都是正整数): 1.Mo ...

  4. Java 面试参考指南 — 同步

    同步 在多线程程序中,同步修饰符用来控制对临界区代码的访问.其中一种方式是用synchronized关键字来保证代码的线程安全性.在Java中,synchronized修饰的代码块或方法不会被多个线程 ...

  5. 维修队列(bzoj 1500)

    Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...

  6. 乘法运算(codevs 3254)

    题目描述 Description 编制一个乘法运算的程序. 从键盘读入2个100以内的正整数,进行乘法运算并以竖式输出. 输入描述 Input Description 输入只有一行,是两个用空格隔开的 ...

  7. 自己写了一个超级简便且傻瓜式的且功能强大的CSV组件(并且代码优雅,绝对没有一行多余的代码)

    github地址: https://github.com/yangfeixxx/chipsCSV.git 解决的问题:解决了传统的CSV工具类对于实体类无法自动化封装为带表头的CSV文件的痛点,在读取 ...

  8. *LOJ#6227. 「网络流 24 题」最长k可重线段集问题

    $n \leq 500$条平面上的线段,问一种挑选方法,使得不存在直线$x=p$与挑选的直线有超过$k$个交点,且选得的直线总长度最长. 横坐标每个点开一个点,一条线段就把对应横坐标连一条容量一费用( ...

  9. ci框架——文章查看之上篇下篇

    1:从数据库查询出推荐的文章的信息,循环查出每篇推荐文章的id和title; foreach($data as $val){ $dataid[]=$val->aid; $datatitle[]= ...

  10. android 完美退出应用程序。

    Android 程序在点击回退键时,如果只有一个activity,调用finish()方法就能退出界面,如果有多个界面,在调用该方法时,只会销毁当前的activity,显示栈顶的其它activity, ...