一、为什么要使用内部类

为什么要使用内部类?在《Think in java》中有这样一句话:使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

在我们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。

  其实使用内部类最大的优点就在于它能够非常好的解决多重继承的问题,但是如果我们不需要解决多重继承问题,那么我们自然可以使用其他的编码方式,但是使用内部类还能够为我们带来如下特性(摘自《Think in java》):

  1、内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。

2、在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。

3、创建内部类对象的时刻并不依赖于外围类对象的创建。

4、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。

5、内部类提供了更好的封装,除了该外围类,其他类都不能访问。

二、成员内部类

成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。

在成员内部类中要注意两点,第一:成员内部类中不能存在任何static的变量和方法;第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。

  1. public class OuterClass {
  2. private String str;
  3.  
  4. public void outerDisplay(){
  5. System.out.println("outerClass...");
  6. }
  7.  
  8. public class InnerClass implements OutInterface{ //继承接口
  9. public void innerDisplay(){
  10. //使用外围内的属性
  11. str = "chenssy...";
  12. System.out.println(str);
  13. //使用外围内的方法
  14. outerDisplay();
  15. }
  16. }
  17.  
  18. /*推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 */
  19. public InnerClass getInnerClass(){
  20. return new InnerClass();
  21. }
  22.  
  23. public static void main(String[] args) {
  24. OuterClass outer = new OuterClass();
  25. OutInterface inner = outer.getInnerClass();  //内部类赋值继承的接口,发生多态且屏蔽内部类细节
  26. inner.innerDisplay();
  27. }
  28. }
  29. --------------------
  30. chenssy...
  31. outerClass...

推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 。

三、局部内部类

有这样一种内部类,它是嵌套在方法和作用于内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。

对于局部内部类实在是想不出什么好例子,所以就引用《Think in java》中的经典例子了。

定义在方法里:

  1. public class Parcel5 {
  2. public Destionation destionation(String str){
  3. class PDestionation implements Destionation{
  4. private String label;
  5. private PDestionation(String whereTo){
  6. label = whereTo;
  7. }
  8. public String readLabel(){
  9. return label;
  10. }
  11. }
  12. return new PDestionation(str);
  13. }
  14.  
  15. public static void main(String[] args) {
  16. Parcel5 parcel5 = new Parcel5();
  17. Destionation d = parcel5.destionation("chenssy"); //局部内部类的多态
  18. }
  19. }

定义在作用域内:

  1. public class Parcel6 {
  2. private void internalTracking(boolean b){
  3. if(b){
  4. class TrackingSlip{
  5. private String id;
  6. TrackingSlip(String s) {
  7. id = s;
  8. }
  9. String getSlip(){
  10. return id;
  11. }
  12. }
  13. TrackingSlip ts = new TrackingSlip("chenssy");
  14. String string = ts.getSlip();
  15. }
  16. }
  17.  
  18. public void track(){
  19. internalTracking(true);
  20. }
  21.  
  22. public static void main(String[] args) {
  23. Parcel6 parcel6 = new Parcel6();
  24. parcel6.track();
  25. }
  26. }

四、匿名内部类

在做Swing编程中,我们经常使用这种方式来绑定事件

  1. button2.addActionListener(
  2. new ActionListener(){
  3. public void actionPerformed(ActionEvent e) {
  4. System.out.println("你按了按钮二");
  5. }
  6. });

我们咋一看可能觉得非常奇怪,因为这个内部类是没有名字的,在看如下这个例子:

  1. public class OuterClass {
  2. public InnerClass getInnerClass(final int num,String str2){
  3. return new InnerClass(){
  4. int number = num + 3;
  5. public int getNumber(){
  6. return number;
  7. }
  8. }; /* 注意:分号不能省 */
  9. }
  10.  
  11. public static void main(String[] args) {
  12. OuterClass out = new OuterClass();
  13. InnerClass inner = out.getInnerClass(2, "chenssy");
  14. System.out.println(inner.getNumber());
  15. }
  16. }
  17.  
  18. interface InnerClass {
  19. int getNumber();
  20. }
  21.  
  22. ----------------
  23. Output:
  24. 5

这里我们就需要看清几个地方

1、 匿名内部类是没有访问修饰符的。

  2、 new 匿名内部类,这个类首先是要存在的。如果我们将那个InnerClass接口注释掉,就会出现编译出错。

3、 注意getInnerClass()方法的形参,第一个形参是用final修饰的,而第二个却没有。同时我们也发现第二个形参在匿名内部类中没有使用过,所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。

4、 匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。

PS:由于篇幅有限,对匿名内部类就介绍到这里,有关更多关于匿名内部类的知识,我就会在下篇博客(java提高篇-----详解匿名内部类)做详细的介绍,包括为何形参要定义成final,怎么对匿名内部类进行初始化等等,敬请期待……

五、静态内部类

在java提高篇-----关键字static中提到Static可以修饰成员变量、方法、代码块,其他它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,不过我们更喜欢称之为嵌套内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:

1、 它的创建是不需要依赖于外围类的。

2、 它不能使用任何外围类的非static成员变量和方法。

  1. public class OuterClass {
  2. private String sex;
  3. public static String name = "chenssy";
  4.  
  5. /**
  6. *静态内部类
  7. */
  8. static class InnerClass1{
  9. /* 在静态内部类中可以存在静态成员 */
  10. public static String _name1 = "chenssy_static";
  11.  
  12. public void display(){
  13. /*
  14. * 静态内部类只能访问外围类的静态成员变量和方法
  15. * 不能访问外围类的非静态成员变量和方法
  16. */
  17. System.out.println("OutClass name :" + name);
  18. }
  19. }
  20.  
  21. /**
  22. * 非静态内部类
  23. */
  24. class InnerClass2{
  25. /* 非静态内部类中不能存在静态成员 */
  26. public String _name2 = "chenssy_inner";
  27. /* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */
  28. public void display(){
  29. System.out.println("OuterClass name:" + name);
  30. }
  31. }
  32.  
  33. /**
  34. * @desc 外围类方法
  35. * @author chenssy
  36. * @data 2013-10-25
  37. * @return void
  38. */
  39. public void display(){
  40. /* 外围类访问静态内部类:内部类. */
  41. System.out.println(InnerClass1._name1);
  42. /* 静态内部类 可以直接创建实例不需要依赖于外围类 */
  43. new InnerClass1().display();
  44.  
  45. /* 非静态内部的创建需要依赖于外围类 */
  46. OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
  47. /* 方位非静态内部类的成员需要使用非静态内部类的实例 */
  48. System.out.println(inner2._name2);
  49. inner2.display();
  50. }
  51.  
  52. public static void main(String[] args) {
  53. OuterClass outer = new OuterClass();
  54. outer.display();
  55. }
  56. }
  57. ----------------
  58. Output:
  59. chenssy_static
  60. OutClass name :chenssy
  61. chenssy_inner
  62. OuterClass namechenssy

上面这个例子充分展现了静态内部类和非静态内部类的区别。

JAVA 内部类 (二)的更多相关文章

  1. Java -- 内部类(二)

    在上一篇博客Java --内部类(一)中已经提过了,java中的内部类主要有四种:成员内部类.局部内部类.匿名内部类.静态内部类. 该文主要介绍这几种内部类. 成员内部类 成员内部类也是最普通的内部类 ...

  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内部类(成员内部类,静态内部类,匿名内部类) * 局部内部类不常用,就不写了. * @package :java05 * @author shaobn * @Describe ...

  6. [转] Java内部类详解

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

  7. Java内部类this$0字段产生的一个bug

    首先查看下面一段代码,我指出了问题代码的所在,读者先自己思考一下这段代码会有什么问题. 这是用clone方法完整拷贝一个二项堆(BinomialHeap)结构的代码.二项堆中包含一个内部类Binomi ...

  8. java内部类实现多继承

    class Example1 { public String name() { return "liutao"; } } class Example2 { public int a ...

  9. js闭包vs Java内部类

    前言: 昨天写了一个关于Java内部的博客,在内部类的最后一点中谈到了Java闭包的概念,他是这样定义闭包的:闭包是一个可调用的对象,它记录了一些信息,这些信息来自创建它的作用域.结合Java的内部类 ...

  10. java内部类的作用

    java内部类的作用 定义: 放在一个类的内部的类我们就叫内部类. 二. 作用: 1.内部类可以很好的实现隐藏 一般的非内部类,是不允许有 private 与protected权限的,但内部类可以 2 ...

随机推荐

  1. react 自定义 百度地图(BMap)组件

    1.html 页面引入 相关js public/index.html <!DOCTYPE html> <html lang="en"> <head&g ...

  2. Mysql导出大量数据

    outfile 导出文件   select name from t1 into outfile "/tmp/test.txt"   infile 导入文件 导入到表t1中的name ...

  3. C++编译错误 2001 1120

    无法解析的外部符号"symbol" 代码引用了链接器无法在库和对象文件中找到的内容(如函数.变量或标签). 该错误信息之后为错误 LNK1120. 可能的原因 : 在将托管库或 W ...

  4. Django-celery分布式任务

    昨天一个很好的面试官问我你在python中怎么实现定时任务呢?我没回答好,我问了下原来有个叫celery的东西,感觉挺好用的 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它 ...

  5. Oracle 索引 简单介绍

    1 索引的创建语法: CREATE UNIUQE | BITMAP INDEX <schema>.<index_name>       ON <schema>.&l ...

  6. Java ClassLoader详解(转载)

    Java ClassLoader详解 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK ...

  7. (Vue)vue模板语法

    Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据.Vue.js 的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统. ...

  8. live555中fDurationInMicroseconds的计算

    live555中fDurationInMicroseconds表示单个视频或者音频帧所占用的时间间隔,也表示在fDurationInMicroseconds微秒时间后再次向Source进行getNex ...

  9. Go怎么获取当前时间? Go ARM64 vDSO优化之路

    https://mzh.io/ Go ARM64 vDSO优化之路 2018-03-16  | Meng Zhuo 背景 Go怎么获取当前时间?问一个会Go的程序员,他随手就能写这个出来给你. imp ...

  10. 2 Maven使用入门

    一.编写pom.xml文件     Maven项目的核心是pom.xml.POM(Project Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等等. ...