如果你看过一些JDK和框架源码的话,就经常会发现一般在类的定义中,都会再定义一些其他的类,这些类也同样会被编译成字节码文件,这样的类就被叫做 内部类

,按照一般的分法,大致可以分为以下四类:

成员内部类

局部内部类

匿名内部类

静态内部类

接下来会针对这四种内部类进行详细讲解,旨在解释这些类的特点和应用场景,如果你懒得看的话,可以直接翻到最底下看总结

我们预先定义好一个类,接来下的所有操作都会在这个类中执行:

class Demo {

public int pubVal = 1;

private int priVal = 1;

public static void staticMethod() {}

public void publicMethod() {}

private void privateMethod() {}

}

复制代码

成员内部类

概念

从名字就可以看出,这种内部类是作为类的成员而存在的,其定义位于类的内部,可以类比为成员变量来理解

实现

class Demo {

// ...

class InternalClass {

}

// ...

}

复制代码

这样就是一个成员内部类了

约束

首先是类定义的约束,实际上,成员内部类的类定义没有任何约束(不涉及static,因为这属于静态内部类的范畴),不仅可以将内部类声明为public、private的,甚至可以将其声明为一个abstract抽象类和interface接口,以及继承外部类也是允许的,其定义是十分宽松的

接着是内部属性和方法,这里就有一些约束了:

不能使用static来修饰任何成员内部类中的属性和方法,但可以使用private、final等其余任意修饰符

可以用static final来修饰成员

可以允许与外部类字段和方法重名

也就是说,成员内部类不能存在静态属性和方法,这么做也是符合成员变量的含义

最后是访问上的约束,这里十分重要:

成员内部类也存在this指针,但是这个指针指向的是自己的引用,如果想访问外部类,需要使用 外部类名.this

这个指针

可以通过 外部类名.静态字段

来访问外部类的静态属性或方法字段

这里的限制就和成员方法是类似的,在理解时可以进行类比

使用

先来说声明,以本文中程序为例,我们可以通过下面的方式来声明一个内部类:

Demo.InternalClass demo

复制代码

注意,如果你将这个内部类声明为private的,外部类依然可以访问,但是外部类之外的其他类是无法访问到的

接着就是通过new来创建,我们在外部类的任何 非静态方法

中,都可以通过new来进行创建,具体格式如下:

Demo.InternalClass demo = new Demo.InternalClass();

复制代码

同样地,我们可以在外部类中,通过内部类的实例来访问其内部的私有变量和方法

局部内部类

我们刚花了大力气来讲解成员内部类,而局部内部类和成员内部类十分类似,可能一些相同的地方我就一笔带过了

概念

局部内部类位于外部类成员方法的内部,可以类比局部变量

实现

public void publicMethod() {

class InternalClass {

}

}

复制代码

约束

这里的约束基本和成员内部类类似,我就单独说一些不同的地方:

其类上不允许有任何修饰符,但是可以使用abstract将类声明为抽象类

不允许将局部内部类声明为接口

不允许使用static来声明成员变量和方法

可以将局部内部类声明在静态方法中

任意两个方法中的局部内部类可以重名

其余的基本和成员内部类类似,把局部内部类当作成员内部类的局部变量版本就好理解了,比如也拥有外部类的指针,使用方法和成员内部类一致

使用

既然是局部内部类,就只能在声明类的方法处来使用,声明和使用方式如下:

public void publicMethod() {

class InternalClass {

}

InternalClass test = new InternalClass();

}

复制代码

同样地,我们依然可以无条件访问内部类中定义的私有属性

匿名内部类

这种内部类应该是我们使用的最多的一种,有时候甚至我们已经使用过了却没有发现

概念

匿名内部类没有类的声明,会隐式地继承一个类或实现一个接口

实现

概念比较抽象,我们直接看是如何定义的,这里我们有一个接受一个对象参数的方法:

private void privateMethod() {

new Demo() {

public int newVal = 20;

@Override

public void publicMethod() {

super.publicMethod();

}

};

}

复制代码

这里的Demo可以换成任意一个类或者接口,你会发现这个类没有名字,所以被叫做匿名内部类

如果Demo是一个普通类,则匿名内部类相当于这个类的子类;如果Demo是一个接口或者抽象类,则这个匿名内部类相当于接口或抽象类的实现

约束

想要理解匿名内部类的约束,就需要将整个匿名内部类不要当成一块程序逻辑来看,而应该当成一个对象来处理,整块匿名内部类完全可以当成一个对象,可以调用对象的方法、属性等等

其主要的约束有以下这些:

不能使用static来修饰方法和属性,但是可以有static final的属性

可以使用this指针来访问本身定义的变量和继承得到的变量,也可以使用 外部类名.this

指针来访问外部类中的所有属性

无法在类上进行任何修饰,因为没有class定义符和类名

其中定义的私有字段对外是完全可见的

使用

这里就不进行过多讲解了,完全和普通对象的用法一致,这里就举两个简单的例子:

int val = new Demo() {

private int newVal = 20;

@Override

public void publicMethod() {

super.publicMethod();

}

}.newVal;

Demo demo = new Demo() {

private int newVal = 20;

@Override

public void publicMethod() {

super.publicMethod();

}

};

复制代码

静态内部类

概念

静态内部类相当于static修饰的成员内部类,可以当作静态变量来理解

实现

class Demo {

// ...

static class InternalClass {

}

// ...

}

复制代码

约束

这里的约束就和之前的有很大不同了,如下:

可以使用任意的修饰符来修饰类、方法和属性

可以访问外部类的静态方法和属性

没错,广义上,静态内部类根本没有约束

使用

使用有以下两种情况:

在外部类的方法中使用时,通过如下语句来创建内部类对象:

InternalClass test = new InternalClass();

复制代码

在外部类之外的其他类可以通过下面的语句来创建内部类对象:

Demo.InternalClass test = new Demo.InternalClass();

复制代码

总结

最后,为大家总结了一张表,基本上内部类的知识点都在这里了:

成员内部类

局部内部类

匿名内部类

静态内部类

类比

成员变量

局部变量

子类或接口的实现类

静态变量

类定义声明位置

类的内部

作用域内部

任意对象可能出现的位置

与成员内部类一致

类修饰符

除static外任意

只允许用abstract修饰

无法修饰

任意的修饰符均可

变量和方法修饰符

除static外任意(但是可以用static final修饰变量)

与成员内部类一致

与成员内部类一致

任意修饰符均可

外部类的访问权限

均可

均可

均可

均可

对象声明位置

只能在外部类的成员方法中,和外部类之外的其余类中声明(如果在外部类之外,要看类访问控制是否允许)

只能在作用域中声明

无需声明

任意位置均可 (如果在外部类之外,要看类访问控制是否允许)

对象创建位置

只能在外部类的成员方法中创建

只能在作用域中创建

立即创建

任意位置均可 (如果在外部类之外,要看类访问控制是否允许)

是否允许有内部类的内部类

可以,但是不允许有静态内部类

与成员内部类一致

与成员内部类一致

可以

java四种内部类区别_浅谈Java中的四种内部类相关推荐

  1. java中单例的应用_浅谈Java中单例模式的几种应用

    目录 浅谈Java中单例模式的几种应用 第一种:懒汉式 第二种:饿汉式 第三种:双重检索式 第四种:注册登记式 第五种:内部类形式 浅谈Java中单例模式的几种应用 日常开发中,为了提高我们系统中对象 ...

  2. java方法区对象类型_浅谈Java内存区域与对象创建过程

    一.java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则 ...

  3. python的re2和re区别_浅谈Python中re.match()和re.search()的使用及区别

    1.re.match()fvk免费资源网 re.match()的概念是从头匹配一个符合规则的字符串,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None.fvk免费资源网 包含的参数如下: ...

  4. java的向下转型_浅谈Java向下转型的意义

    一开始学习 Java 时不重视向下转型.一直搞不清楚向下转型的意义和用途,不清楚其实就是不会,那开发的过程肯定也想不到用向下转型. 其实向上转型和向下转型都是很重要的,可能我们平时见向上转型多一点,向 ...

  5. java字符串常量存哪里_浅谈JAVA中字符串常量的储存位置

    在讲述这些之前我们需要一些预备知识: Java的内存结构我们可以通过两个方面去看待它. 从该角度看的话Java内存结构包含以下部分:该部分内容可以结合:JVM简介(更加详细深入的介绍) 1.栈区:由编 ...

  6. java接口是干啥_浅谈Java接口

    接口(英文:Interface)是Java中非常重要的内容,初学的时候可能感受不深,但是在做项目的时候,对面向接口编程的运用就变得尤为重要,不过这是后话了.现在先讨论假如是刚刚接触接口这个概念,该怎么 ...

  7. workbench设置单元坐标系_浅谈Ansys中的几种坐标系

    这篇简短的文章是我多年前在仿真论坛任ansys版主时发表的,时隔多年,同事正好咨询关于ansys坐标系的知识,就将此贴翻出来解他困惑,自己也重温下当年的技术贴,发给大家,希望对学习ansys的初学者有 ...

  8. java类的命名规范_浅谈Java中的命名规范

    现代软件架构的复杂性需要协同开发完成,如何高效地协同呢? 答案是:制定一整套统一的规范. 无规矩不成方圆,无规范难以协同,比如,制订交通法规表面上是要限制行车权,实际上是保障公众的人身安全,试想如果没 ...

  9. python中for循环和while循环的区别_浅谈python中的while循环

    python中有两种循环,while和for,两种循环的区别是,while循环之前,先判断一次,如果满足条件的话,再循环:for循环的时候必须有一个可迭代的对象,才能循环,比如说 列表.字典.字符串等 ...

最新文章

  1. 转:场景管理--BSP
  2. Python_List对象内置方法详解
  3. 2021高考萧山二中成绩查询,萧山中学2018高考成绩
  4. 科沃斯机器人电池激活_扫地机器人充不进去电怎么办
  5. 【bzoj1597】 土地购买
  6. for循环执行 mybatis_mybatis sql循环的使用
  7. 微信对账单 java_微信支付对账,你是如何处理的?
  8. 创建类(点击获得位置信息)—ArcGIS API for JavaScript
  9. iOS中使用SFHFKeychainUtils保存用户密码
  10. 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)
  11. java链式语法_javaScript链式调用原理以及加法实现
  12. Atitit 自然语言与人工语言的语法构建ast的异同点 目录 1. 语言节点gaishu。。 2 1.1. 节点、函数数量大约200个 2 1.2. 关键词节点 是 有 的 3 1.3. 标识符
  13. 黑莓9000和9900哪个好_入手黑莓9900,黑莓手机9900怎么样?
  14. codeblock 添加 .lib 文件
  15. termux安装gcc
  16. 用Python 计算t分布的置信区间
  17. 软件工程网络15个人作业3(201521123010徐璐琳)
  18. SAP第四代增强 BTE
  19. 测试家里网速用什么软件,家中宽带网速多少?教你测试小妙招
  20. 淘宝客小程序制作(4)-小程序(微信支付宝)

热门文章

  1. 云时代,运维要么自己写代码,要么开发替你写了
  2. 新功能又来啦!这次是「代码搜索」和视频直播!
  3. 台积电9月14日起不向华为供货;315曝光50多款App涉嫌内置SDK窃取隐私;Micronaut 1.3.7发布 | 极客头条...
  4. 阿里 P8 员工招聘私人助理被辞退;微信上线「拍一拍」功能;FreeBSD 11.4 释出 | 极客头条...
  5. GitHub 标星 10,000+,Apache 顶级项目 ShardingSphere 的开源之路
  6. 确认!这样学习 Python 能甩同行 10 条街!
  7. 亚信科技公布2019年度业绩,5G商用效果凸显
  8. Python 数据分析实战,揭秘国内顶尖医院分布现状!
  9. 如何从零开始制作智能桌宠?
  10. 针对金融级交易场景的严苛技术要求,如何修炼这门“必修课”?