编写java程序时,一般一个类(或者接口)都是放在一个独立的java文件中,并且类名同文件名(如果类是public的,类名必须与文件名一致;非public得,无强制要求)。如果想把多个java类放在一个java文件中,则只能有一个public类。如下面的两个类放在同一个文件中就会报错,无法编译通过。

可以看出,因为TestOne.java文件中已经有一个public类TestOne,这时再加了一个public类TestTwo就报错了。如果将类TestTwo前面的public修饰符去掉就没有问题了。

我们下面介绍内部类的概念和使用,所谓内部类,简单的说,就是一个类定义在另一个类的内部。与上面的两个类在同一个文件中不同(TestOne和TestTwo虽然在一个文件中,但相互没有嵌套,是并列的)。

采用内部类,有时会对代码的可读性带来一点问题,但很多场景下还是很有必要的。尤其在使用一些框架(如java的swing,集合框架中的排序操作)等,使用内部类(尤其是匿名内部类)会带来很多便利;再比如我们在开发Android app时,就会大量的使用内部类,如果不了解内部类的含义和使用规则,几乎无法顺利的进行Android app的开发。

内部类有其特别的地方,其中核心之一是,内部类实例可以访问包含它的外部类的所有成员,包括private成员。另外非常关键的一点是,内部类的使用必须与一个外部类的实例绑定,注意是实例,后面的例子中会说明这点。

内部类也分好几种情况,下面一一来解释。

一、一般内部类

例1:TestTwo就是一个内部类,它可以直接访问外部类中的私有成员a。

public class TestOne {private int a = 2;public static void main(String[] args) {new TestOne().call();}public void call(){TestTwo two = new TestTwo();two.show();}class TestTwo {public void show(){System.out.println(a);}}
}

 例2:如果需要在外部类的静态方法中使用内部类,必须创建一个外部类的实例,通过该实例来new内部类。不能直接new,否则会报编译错误。

public class TestOne {private int a = 2;public static void main(String[] args) {TestOne testOne = new TestOne();TestTwo testTwo = testOne.new TestTwo();testTwo.show();}public void call(){TestTwo two = new TestTwo();two.show();}class TestTwo {public void show(){System.out.println(a);}}
}

 例3:如何在内部类中引用外部类的实例。有两种方法,一是普通的方法,在new内部类时,将外部类的this作为内部类的构造函数参数传给内部类;还有一种更简单的方法,直接在内部类中通过 "外部类类名.this" 就可以使用外部类的实例。如下面代码:

public class TestOne {private int a = 2;public static void main(String[] args) {new TestOne().call();}public void call(){new TestTwo(this).show();}class TestTwo {private TestOne one;public TestTwo(TestOne one){this.one = one;}public void show(){System.out.println(a);System.out.println(one.a);System.out.println(TestOne.this.a);}}
}

上述情况下使用内部类,通常该内部类只是被该外部类使用,这样可以对内部类起到隐藏作用,并且跟外部类绑定的更紧密。

二、方法内的内部类

就是内部类定义在一个方法的内部。这种情况下,只有在该方法内才能使用该内部类;内部类也可以访问外部类的成员;但注意不能访问包含它的方法的局部变量(包括参数),除非方法内的变量(或参数)是final的。 举例:

public class TestOne {private int a = 2;public static void main(String[] args) {new TestOne().call();}public void call(){final int b=3;class TestTwo {private TestOne one;public TestTwo(TestOne one){this.one = one;}public void show(){System.out.println(a);System.out.println(one.a);System.out.println(TestOne.this.a);System.out.println(b);}}new TestTwo(this).show();}
}

  需要注意的是,如果是在静态方法中定义内部类,则该内部类只能使用外部类的静态成员。

三、匿名内部类

匿名内部类,其实也分很多情况。最常见的情况是,直接通过父类(比如抽象类)创建子类的实例,或直接通过接口创建对象,该对象可传递作为方法的参数,或者赋值给某个变量。实际上在内部类的使用中,匿名类是用途最广泛的。

因为我们都知道,在java中,一般情况下,不像c/c++一样,我们可以把一个方法作为一个变量进行传递或引用。

我们只能传递和引用java对象。比如我们定义了一个方法,有个参数是接口类型或抽象类,这样不使用匿名内部类,我们每次都需要先定义一个类实现该接口或抽象类,再创建该类的实例传递给该方法。当接口或抽象类中需要实现的方法数量比较少时(比如只有1个),这个先创建类,再使用就显的比较啰嗦了。而且这种场景下,往往创建的类就这一个地方使用。而通过匿名内部类,就可以让编写的代码简洁很多。 实际上,java本身提供的一些api(如多线程、io、集合框架等)就大量的使用了这个特性。 我们来看几个例子:

例1:通过接口创建对象

public class TestThread {public static void main(String[] args) {TestThread testThread = new TestThread();testThread.fun1();testThread.fun2();}public void fun1(){Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("fun1");}};new Thread(runnable).start();}public void fun2(){new Thread(new Runnable() {@Overridepublic void run() {System.out.println("fun2");}}).start();}
}

可以看出,方法fun1中直接通过Runnable接口创建了对象,供Thread类使用。fun2更简化了下,直接连变量名也省掉了,对象的创建直接在传入参数时创建。

例2:直接创建父类的子类对象

public class TestChild {public static void main(String[] args) {new Thread() {@Overridepublic void run() {System.out.println("thread is run");}}.start();}
}

  可以看出,Thread类有一个run方法,但这个run方法是空的,我们如果要用继承Thread类来实现多线程,必须在子类中重载run方法。上面的代码我们实际上没有显示的定义一个Thread的子类,而是直接通过上述形式创建了一个线程实例,并启动它。

四、静态嵌套类(内部类)

也就是在一个类中定义一个静态类(注意不能在方法中定义)。 与前面介绍的内部类不同。这个嵌套类只是命名空间限制在外部类中。实质上它不需要与外部类的实例绑定,也无法访问外部类的实例成员,只能访问外部类的静态成员。代码如:

public class TestOne {private int a = 2;static private int b = 2;public static void main(String[] args) {TestTwo testTwo = new TestTwo();}public void call(){TestTwo testTwo = new TestTwo();}static class TestTwo {public void show(){System.out.println(b);}}
}class TestThree{public static void main(String[] args) {TestOne.TestTwo testTwo = new TestOne.TestTwo();}public void call(){TestOne.TestTwo testTwo = new TestOne.TestTwo();}
}

可以看出,TestTwo的使用不需要依赖外部类TestOne的实例。

上面介绍了内部类的几种情况,使用的时候稍加注意即可。  

转载于:https://www.cnblogs.com/51kata/p/4125704.html

Java学习笔记:内部类/匿名内部类的全面介绍相关推荐

  1. Java学习笔记:Javaweb的服务器介绍

    Java Web,是用Java技术来解决相关web互联网领域的技术总和.web包括:web服务器和web客户端两部分.Java在客户端的应用有java applet,不过使用得很少,Java在服务器端 ...

  2. 【Java学习笔记之二十六】深入理解Java匿名内部类

    在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...

  3. 郑志远的java学习笔记

    郑志远的java学习笔记 郑志远    CCB 1         Java起源 略 2         Java语言概述 1.面向对象编程的3个原则:封装(encapsulation).继承(inh ...

  4. java学习笔记9--内部类总结

    java学习笔记系列: java学习笔记8--接口总结 java学习笔记7--抽象类与抽象方法 java学习笔记6--类的继承.Object类 java学习笔记5--类的方法 java学习笔记4--对 ...

  5. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  6. 2022年Java学习笔记目录

    一.2022年Java任务驱动课程 任务驱动,统摄知识点:2022年Java程序设计讲课笔记 二.2022年Java学习笔记 (一)踏上Java开发之旅 Java学习笔记1.1.1 搭建Java开发环 ...

  7. Java 学习笔记 - 数组类型互转

    Java 学习笔记 - 数组类型互转 数组类型转换 字符串数组 to (Integer.Long.Double)列表 传统方式 Java8 Stream方式 数组 to 数组 字符串数组 to (in ...

  8. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

  9. Java学习笔记之log4j与commons-logging转

    Java学习笔记之log4j与commons-logging<转> (2011-02-16 11:10:46) 转载▼ 标签: 杂谈 分类: 技术学习之其他 Logger来自log4j自己 ...

  10. Java学习笔记22:并发(2)

    Java学习笔记22:并发(2) 图源:PHP中文网 终止任务 终止线程有一种非常简单的方式:设置一个多线程共享的标记位,子线程用轮询的方式检查这个标记位,如果该标记位显示取消状态,就让子线程退出执行 ...

最新文章

  1. Android 内存管理 amp;Memory Leak amp; OOM 分析
  2. js、jquery实用小技巧集合
  3. WCF服务端调用client.
  4. 学生电脑哪个牌子好_常亮补光灯哪个牌子好服务至上
  5. 【今日CV 计算机视觉论文速览 91期】Mon, 1 Apr 2019
  6. Matplotlib使用指南
  7. 用递归方法实现读取文件夹下所有文件信息
  8. _declspec(dllexport)与_declspec(dllimport)
  9. 内存对齐的规则与作用
  10. linux实验考试题
  11. php 死链查询,网站最新死链查询和处理方法
  12. 将shapefile文件加工为FBX文件、glb文件、gltf文件
  13. 消防工程师 10.3 火灾自动报警系统-可燃气体、电气火灾、消控室 11.灭火器
  14. web测试----死链检查(Xenu)
  15. 什么是安迪比尔定理?
  16. cos三次方积分_COS分之一三次方积分
  17. SWAN测试用例af-alg/rw-cert
  18. (转)人在德国:芦笋季节话芦笋
  19. xmanager 5图文使用教程
  20. okio 原理分析(一)

热门文章

  1. jiebaR中文分词,从入门到喜欢
  2. java 文件 加解密_Java实现文件的加密解密功能示例
  3. 系统架构图怎么画_基于ROS的移动机器人上层系统架构分析
  4. python环境变量配置_Anaconda从下载到环境变量配置(windows)
  5. 两边放动物对战守城的游戏_集合啦!动物森友会定制周边;百战天虫 大混战发布...
  6. python中国余数定理_Python实现的中国剩余定理算法示例
  7. android获取wifi连接状态,获取android设备wifi连接状态
  8. linux 重新分区挂载,Linux:挂载磁盘分区,linux已挂载磁盘重新分区
  9. python判断素数的函数_Python素数prime函数练习_Python源码实操
  10. 大智慧825 自选股 导出_互联网技术更新智慧党校迎来发展契机-威尔 WEDS-BP31_济南考勤机行情...