内部类的访问规则

  • 内部类可以直接访问外部类中的成员,包括私有成员。

    因为内部类中持有了一个外部类的引用,格式为:外部类名.this
  • 外部类要访问内部类,必须要建立内部对象。
  1. class Outer { //外部类
  2. private int x = 1;
  3. class Inner{ //内部类
  4. int x = 2;
  5. void function() {
  6. int x = 3;
  7. System.out.println(x);
  8. System.out.println(this.x);
  9. System.out.println(Outer.this.x);
  10. }
  11. }
  12. void method() {
  13. Inner in = new Inner();
  14. in.function();
  15. }
  16. }
  17. public class InnerClassDemo {
  18. public static void main(String[] args) {
  19. Outer out = new Outer();
  20. out.method();
  21. Outer.Inner in = new Outer().new Inner();
  22. in.function();
  23. }
  24. }

运行结果:

  1. 3
  2. 2
  3. 1
  4. 3
  5. 2
  6. 1

访问

  1. 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象。

    格式: 外部类名.内部类名 变量名 = 外部类对象.内部类对象;
  2. 当内部类在成员位置上,就可以被成员修饰符所修饰。

    例如:private,将内部类在外部类中进行封装。

    static:使得内部类具有static的特性。(当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问的局限。)

静态内部类

  • 在外部其他类中,如何直接访问静态内部类的非静态成员
  1. class Outer {
  2. private static int x = 1;
  3. static class Inner {
  4. void function() {
  5. System.out.println(x);
  6. }
  7. }
  8. }
  9. public class InnerDemo2 {
  10. public static void main(String[] args) {
  11. new Outer.Inner().function();
  12. }
  13. }
  • 在外部其他类中,如何直接访问静态内部类的静态成员
  1. class Outer {
  2. private static int x = 1;
  3. static class Inner {
  4. static void function() {
  5. System.out.println(x);
  6. }
  7. }
  8. }
  9. public class InnerDemo3 {
  10. public static void main(String[] args) {
  11. Outer.Inner.function();
  12. }
  13. }
  • 当内部类中定义了静态成员,该内部类必须也是静态的

    以下代码编译会导致编译错误
  1. class Outer {
  2. private static int x = 1;
  3. class Inner { //此内部类中定义了静态成员但是此内部类不为静态
  4. static void function() {
  5. System.out.println(x);
  6. }
  7. }
  8. }
  9. public class InnerDemo3 {
  10. public static void main(String[] args) {
  11. Outer.Inner.function();
  12. }
  13. }
  • 当外部类中的静态方法访问内部类时,内部类也必须是静态的。

内部类的定义原则

当描述一个事物时,这个事物的内部有事物,此时这个内部的事物需要使用内部类来描述。

局部内部类

  • 内部类定义在局部时:
  1. 不可以被成员修饰符修饰。
  2. 可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部变量,只能访问被final修饰的局部变量。(目前版本的jdk中,final可以省略)
  1. class Outer {
  2. void method(final int x) {
  3. class Inner {
  4. void function() {
  5. System.out.println(x);
  6. }
  7. }
  8. new Inner().function();
  9. }
  10. }
  11. public class InnerDemo4 {
  12. public static void main(String[] args) {
  13. Outer out = new Outer();
  14. out.method(7);
  15. out.method(8);//因为局部变量在栈内存中,每次一调用入栈,使用结束出栈。所以虽然是被final修饰,但是仍然可以重复调用。
  16. }
  17. }

运行结果:

  1. 7
  2. 8

匿名内部类

  1. 匿名内部类其实是内部类的简写格式。
  2. 定义匿名内部类的前提:

    内部类必须是继承一个类或者实现接口。
  3. 匿名内部类的格式:new 父类或者接口(){定义子类的内容}
  1. abstract class Abs {
  2. abstract void method();
  3. }
  4. class Outer {
  5. int x = 3;
  6. /*class Inner extends Abs {
  7. @Override
  8. void mthod() {
  9. System.out.println(x);
  10. }
  11. }*/
  12. public void function() {
  13. //new Inner().mthod();
  14. new Abs() {
  15. @Override
  16. void method() {
  17. System.out.println(x);
  18. }
  19. }.method();
  20. }
  21. }
  22. public class InnerDemo5 {
  23. public static void main(String[] args) {
  24. new Outer().function();
  25. }
  26. }

运行结果

  1. 3

以上代码将注释部分,用匿名内部类的形式体现了出来。

  1. 匿名内部类是一个匿名子类对象。可以理解为带内容的对象。
  2. 匿名内部类中定义的方法最好不要超过3个。
  3. 如果一个类既没有实现接口也没有继承父类,可以使用Object类来创建匿名内部类。

    例如:
  1. public class InnerClassTest {
  2. public static void main(String[] args) {
  3. new Object() { //如果左边有Object类型引用(Object ob = ),将无法调用method方法
  4. public void method() {
  5. System.out.println("method run");
  6. }
  7. }.method();
  8. }
  9. }

练习

  1. interface Inter {
  2. void method();
  3. }
  4. class Test {
  5. //补足代码,通过匿名内部类
  6. }
  7. public class InnerClassTest {
  8. public static void main(String[] args) {
  9. Test.function().method();
  10. }
  11. }

分析 Test.function().method(); 这行代码可以发现function()应该是Test类中一个静态方法,function()方法后面还有一个method()的调用,说明调用function()方法应是返回了一个对象而且是Inner类型的对象,从而才能继续调用method()方法。

可以得到以下代码:

  1. interface Inter {
  2. void method();
  3. }
  4. class Test {
  5. //补足代码,通过匿名内部类
  6. static Inter function() { //这里返回值类型为Inner
  7. return new Inter(){
  8. @Override
  9. public void method() {
  10. System.out.println("Hello World");
  11. }
  12. };
  13. }
  14. }
  15. public class InnerClassTest {
  16. public static void main(String[] args) {
  17. Test.function().method();
  18. }
  19. }

Java学习笔记(十二)面向对象---内部类的更多相关文章

  1. Java学习笔记十二:Java中方法的重载

    Java中方法的重载 什么是方法的重载呢? 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方法名称都为 s ...

  2. Java学习笔记十二--集合(三)

    第一节课 返回值 方法名 作用 void add(index,elemnet) 在指定的索引处添加元素 object get(index) 返回指定索引处的元素 int indexOf(object) ...

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

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

  4. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  5. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  6. 【Java学习笔记之二十五】初步认知Java内部类

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

  7. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  8. Java学习笔记(二)——Java操作properties文件

    [前面的话] 前段时间在学习和玩java web相关的东西,对于这些技术,一边学习,一边做东西,一边总结,希望可以一边成长和有所收获.有时总是思考太多反而成为了前进的阻力,所以对于生活还是简单一些,不 ...

  9. 从.Net到Java学习第十二篇——SpringBoot+JPA提供跨域接口

    从.Net到Java学习系列目录 最近又撸了半个月的前端代码,做app离线存储,然后又花了一周去将过去的wcf项目转webapi,java又被落下了,总感觉我特么像斗地主中的癞子牌,变来变去..... ...

随机推荐

  1. 查找第K大的值

    这种题一般是给定N个数,然后N个数之间通过某种计算得到了新的数列,求这新的数列的第K大的值 POJ3579 题意: 用$N$个数的序列$x[i]$,生成一个新序列$b$. 新的序列定义为:对于任意的$ ...

  2. Oracle的overlaps函数转换其他数据库语法

    首先,来介绍一下Oracle的overlaps函数的用法: overlaps函数是用来判断两个时间段是否有重叠的 比如说计算 (a,b),(c,d) 就可以写成: select * from dual ...

  3. 【STM32H7教程】第47章 STM32H7的FMC总线基础知识和HAL库API

    完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第47章       STM32H7的FMC总线基础知识和HA ...

  4. c# 异步编程总结

    异步编程前提 1.学委托 delegate 其中委托中的beginInvoke()和endInvoke()方法必须要会. 2.学习回调函数 (也可以不用,但是一般建议用回调函数中执行endinvoke ...

  5. C#实现的Table的Merge,以及实现Table的Copy和Clone

    C#实现的对两个Table进行Merge,两表必须存在至少一个公共栏位作为连接项,否则连接就失去了意义.如下是对两个table进行Merge的详细代码: private void button1_Cl ...

  6. mysql常见问题解决方案

    属性顺序错误 一般情况下字段类型要放在前面,限制参数放在后面,UNSIGNEDZEROFILL 之间没有先后顺序,主键 KEY 和 auto_increment 要放在UNSIGNED ZEROFIL ...

  7. opencv —— HoughLines、HoughLinesP 霍夫线变换原理(标准霍夫线变换、多尺度霍夫线变换、累积概率霍夫线变换)及直线检测

    霍夫线变换的原理 一条直线在图像二维空间可由两个变量表示,有以下两种情况: ① 在笛卡尔坐标系中:可由参数斜率和截距(k,b)表示. ② 在极坐标系中:可由参数极经和极角(r,θ)表示. 对于霍夫线变 ...

  8. 一台服务器搭建部署两个或多个Redis实例

    问题描述: 今天程序那边说测试服里面有两个项目,为了数据不冲突,想一台服务器搞两个Redis实例, 然后自己这边查询了一下,确实可以这么整,只需要区分端口号和区分配置文件方面就行, 原理与nginx和 ...

  9. k8s 在Centos上 安装

    k8s安装步骤: 1.所有机器上执行以下命令,准备安装环境:(注意是所有机器,主机master,从机node都要安装) 1.1.安装epel-release源(EPEL (Extra Packages ...

  10. DataReader类型化数据读取与装箱性能研究

    前言 在各种ORM框架或者SQL映射框架(例如MyBatis,SOD框架之SQL-MAP功能)中,都有将查询的结果映射为内存对象的需求,包括映射到实体类.简单类型(例如Java的POJO,.NET的P ...