JAVA 类总结
JAVA 类总结
最近看了遍java内部类相关的一些内容,做一些总结。与个人博客 zhiheng.me 同步发布,标题: JAVA 类总结。
顶级类与嵌套类
定义在某个类(或接口,下同)内部的类,称为嵌套类(nested class),相应的,其所在的类称之为该类的外围类(enclosing class)或包裹类。
非嵌套类称为顶级类(top-level class),一个 .java 文件中可以有若干个顶级类(含抽象类和接口),但只能有一个被 public 修饰的类,且该类必须和 .java 文件同名。
顶级类的访问修饰符只能是 public 和包访问权限(默认权限,无修饰符)。
嵌套类可看作是外围类的一个成员,因此其修饰符可以是 public 、protected 、包访问权限和 private 。
嵌套类没有层次限制,可以在嵌套类里面在定义类,成为嵌套类中的嵌套类。
嵌套类分为两种,一种是静态的(用 static 关键字修饰)称为静态嵌套类(static nested class);一种是非静态的,称为内部类(inner class)。
注:在《Think in Java》一书中,作者将内部类定义为“将一个类定义在另一个类的定义内部,则这个类就是内部类”,因此,他将静态嵌套类视为内部类的一种。而本文使用了 java 官方文档中的定义。
内部类一般直接定义在外部类(outer class)中,就像该类的一个成员一样,我们把这样的内部类称为成员内部类(member inner class)。即不在构造器、方法、语句块中定义的内部类为成员内部类。
除成员内部类外还有另外两种较特殊的内部类:局部内部类(local class)和匿名内部类(anonymous class)。
嵌套类字节码文件命名
嵌套类经编译后会自动生成独立的字节码文件(.class),其命名格式:
外部类名称+\$+[该种类同名类中该类顺序]+[内部类名称]
以下代码(文件名:Outer.java)中含有静态类 Static 、成员内部类 Inner 、局部类 Local 、实现 Anonymous 接口的匿名类以及定义在该源文件中的接口 Anonymous 。
package thinkinjava; public class Outer { public static class Static{} public class Inner {} {
class Local{};
} Anonymous anonymous = new Anonymous(){};
} interface Anonymous {}
编译后形成了如下6个 .class 字节码文件。顶级类 Outer 和 Anonymous 都被编译成同名的 class 文件,静态嵌套类 Static 和成员内部类 Inner 被编译成了 Outer\$Static.class 和 Outer\$Inner.class ,因为成员类不能同名,所以也就没有同名类顺序。局部类 Local 编译后的文件名是 Outer\$1Local.class ,因为 Outer 类中只有一个名为 Local 的局部类,因此,其顺序是1。匿名类没有名称,所以编译后的文件名是 Outer\$1.class ,1表示该类是 Outer 类中第一个匿名类。
Anonymous.class
Outer$1.class
Outer$1Local.class
Outer$Inner.class
Outer$Static.class
Outer.class
静态嵌套类
public class OuterClass{
public static class NestClass{}
}
静态嵌套类因为是静态的,因此从本质上来说它和外部类的关系更像是类与包(package)的关系。在其他类中引用使用的时候需要加上外部类限定: OuterClass.NestClass
。
- 与静态方法一样,静态嵌套类中不能访问外部类的非静态成员和非静态方法(不管是public还是private的);
- 静态嵌套类的实例化(instantiate)无需事先实例化外部类,因为静态嵌套类是与外部类直接相关联的,而非与外部类的实例(instance)相关联。
内部类
内部类是非静态的,因此内部类是与外部类的实例相关联的。在实例化内部类时,必须先行实例化外部类,再通过外部类的实例来创建内部类的实例:
OuterClass outObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
- 内部类中不能有 static 关键字修饰的静态成员(块、字段、方法、接口等),除非该成员是静态常量。所以,内部类中的静态成员必须是同时使用 final 关键字修饰的字段。
- 内部类可以访问外部类的任何成员(包括构造器),不管是公有的还是私有的,静态的还是非静态的。同样,外部类也可以访问到内部类的所有成员。
遮蔽(Shadowing)
定义在内部类或成员方法内的字段或参数,如果和外部作用域内的某个成员变量定义同名,那么外部的定义将被遮蔽,此时无法在内部作用域内仅通过名字访问到外部的成员。以下是摘自 Java Tutorial 中的一个例子:
public class ShadowTest { public int x = 0; class FirstLevel { public int x = 1; void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
} public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}
// 输出如下
// x = 23
// this.x = 1
// ShadowTest.this.x = 0
局部内部类
局部类是定义在某个块(block)中的类。即定义在构造器、方法、循环体、分支结构(if 子句)中的类。
- 同局部变量,局部类不能用public,private,protected,static修饰,但可以被final或者abstract修饰。
- 局部类是内部类,因此可以访问其外部类的成员。但局部类的作用域在块内,所以外部类无法访问到局部内部类。
局部类属于块的作用域,因此可以访问局部变量(包括形参),但是只能访问用 final 修饰的局部变量。
在 Java SE 8 之后,局部类可以访问 effectively final 的局部变量和非 final 的形参了,effectively final 的变量没有 final 修饰但在初始化后从未改变过值。 “A variable or parameter whose value is never changed after it is initialized is effectively final” 。
匿名类
匿名类,顾名思义就是没有名称的类,没有名称也就无法在其他地方引用和实例化,当然也就没有构造器。匿名类在定义的同时会实例化本身(匿名类只实例化这一次)。
匿名类的定义从形式上看更像是一种表达式,也就是类的定义出现在一个表达式中。从语法形式上看,匿名类的定义像是调用了一个构造器。以下是几种匿名类的例子:
public class Test {
InterfaceA a = new InterfaceA() {};//成员匿名类
public static void main(String[] args){
InterfaceA a = new InterfaceA() {};//局部匿名类
//以上两种是通过实现接口实现匿名类,称为接口式匿名类,也可以通过继承类实现
Test test = new Test(){};//继承式匿名类
//还可以是位于参数上
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();//属于局部匿名类一种
}
private interface InterfaceA{}
}
匿名类不能使用任何关键字和访问控制符,匿名类和局部类访问规则一样,只不过内部类显式的定义了一个类,然后通过new的方式创建这个局部类实例,而匿名类直接new一个类实例。
JAVA 类总结的更多相关文章
- 如何用Java类配置Spring MVC(不通过web.xml和XML方式)
DispatcherServlet是Spring MVC的核心,按照传统方式, 需要把它配置到web.xml中. 我个人比较不喜欢XML配置方式, XML看起来太累, 冗长繁琐. 还好借助于Servl ...
- jvm系列(一):java类的加载机制
java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...
- java类与实例
最近在看设计模式,感觉自己对java的三大特性的理解不够清晰,搞不清楚抽象类.接口.泛型的用处和优缺点.设计模式学了一半,想着还是停下来脑补一下java的基础,就从java对象开始吧. 一.java对 ...
- oracle调用JAVA类的方法
导入jar包 在oracle中导入需要的jar包,我们把编辑好的java类打成jar包,直接在oarcle里面写简单的调用就可以了, 1.操作系统需要拥有支持loadjava命令的jdk. 2.加 ...
- Java 类的实例变量初始化的过程 静态块、非静态块、构造函数的加载顺序
先看一道Java面试题: public class Baset { private String baseName = "base"; // 构造方法 public Baset() ...
- hibernate中java类的成员变量类型如何映射到SQL中的数据类型变化
hibernate映射文件??.hbm.xml配置映射元素详解--Hibernate映射类型 在从Hibernate的java的成员类型映射到SQL中的数据类型,其内映射方式它满足,SQL可以自己调制 ...
- kettle系列-[KettleUtil]kettle插件,类似kettle的自定义java类控件
该kettle插件功能类似kettle现有的定义java类插件,自定java类插件主要是支持在kettle中直接编写java代码实现自定特殊功能,而本控件主要是将自定义代码转移到jar包,就是说自定义 ...
- Myeclipse中导入项目后java类中汉字注释出现乱码问题(已解决)
今天重装系统,安装了新的Myeclipse后,导入之前的项目后,,出现了乱码问题.乱码问题主要是java类中的注释,而jsp页面中汉字却完好如初: 右键项目,查看项目的编码格式,UTF-8,把java ...
- Java类初始化
Java类初始化 成员变量的初始化和构造器 如果类的成员变量在定义时没有进行显示的初始化赋值,Java会给每个成员变量一个默认值 对于 char.short.byte.int.long.float. ...
- 深入研究Java类装载机制
目录 1.为什么要研究java类装在机制? 2.了解类装载机制,对于我们在项目开发中有什么作用? 3.装载实现细节. 4.总结 一.为什么药研究Java类装载机制 java类加载机制,便于我们使用自定 ...
随机推荐
- MongoDB基础之九 replication复制集
准备工作:创建目录 mkdir -p /home/m17 //home/m18 /home/m19 /home/mlog 1:启动3个实例,且声明实例属于某复制集 # ./bin/mongod --d ...
- 【.Net Framework 体积大?】不安装.net framework 也能运行!?开篇叙述-1
[声明:请尊重作者micro-chen的原创,抓文章,请添加来源和作者署名.作者保留追责权利.......] 写在前言 看着日渐没落的.net ,心里多少有了点悲凉.国内的越来越多的新兴公司 都是JA ...
- JavaScript嗅探执行神器-sniffer.js,你值得拥有!
一.热身--先看实战代码 a.js 文件 // 定义Wall及内部方法 ;(function(window, FUNC, undefined){ var name = 'wall'; Wall.say ...
- winsshfs的快速入手
之前在公司使用mac ,并且通过mac下的osfuse和sshfs连接,直接将虚拟机的文件目录同步到了本地,并且可以进行实时操作修改,对于写项目,确实是省了很大一部分上传的精力. 于是在自己的win下 ...
- 用js实现文字提示层 ---总结
文字提示层在项目中应该是比较常见的,我工作中项目中就用到了,原理是一样,只不过形式不一样,今天通过看视频学习,学会了,总结下: 首先,页面效果如下: 需求: 当鼠标移入到红色字体是,提示框会显示在下 ...
- devexpress表格控件gridcontrol图片列,按钮列,时间列等特殊列的实现
1.项目中经常会在表格中插入按钮列,图片列,表格列一些非文本的特殊列.如何在devexpress表格控件gridcontrol中实现呢?以下列举一个实现添加图片列,按钮列,时间列,按钮列,开关列的示例 ...
- [看图说话] 基于Spark UI性能优化与调试——初级篇
Spark有几种部署的模式,单机版.集群版等等,平时单机版在数据量不大的时候可以跟传统的java程序一样进行断电调试.但是在集群上调试就比较麻烦了...远程断点不太方便,只能通过Log的形式,进行分析 ...
- SuperWebClient -一个基于CURL的.NET HTTP/HTTPS模拟神组件(2)
今天我们讨论SuperWebClient组件使用中的几个简单主题 1: UserAgent2: Cookies3: POST登录 1:UserAgent这个是客户端标识信息,此信息是用于鉴别正在访问W ...
- 每天一个Linux命令(18)--locate命令
locate让使用者可以很快速的搜寻档案系统内是否有指定的档案.器方法是先建立一个包括系统内所有档案名称及路径的数据库,之后当寻找时就需查询这个数据库,而不必实际深入档案系统之中了.在一般的 ditr ...
- ERP实施员的保密要求
一.公司机密文件范围 1 公司级计算机密码 2 公司级程序软件 3 与客户联系的各种远程联系用户名,密码 4 公司发展计划.规划 5 公司客户资料.财务报表.人事薪资.报 ...