提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比。内部类从表面上看,就是在类中又定义了一个类(下文会看到,内部类可以在很多地方定义),而实际上并没有那么简单,乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的深入了解,你会发现Java的设计者在内部类身上的确是用心良苦。学会使用内部类,是掌握Java高级编程的一部分,它可以让你更优雅地设计你的程序结构。下面从以下几个方面来介绍:
public interface Contents {
int value();
}
public interface Destination {
String readLabel();
}
public class Goods {
private class Content implements Contents {
private int i = 11;
public int value() {
return i;
}
}
protected class GDestination implements Destination {
private String label;
private GDestination(String whereTo) {
label = whereTo;
}
public String readLabel() {
return label;
}
}
public Destination dest(String s) {
return new GDestination(s);
}
public Contents cont() {
return new Content();
}
}
class TestGoods {
public static void main(String[] args) {
Goods p = new Goods();
Contents c = p.cont();
Destination d = p.dest("Beijing");
}
}
在这个例子里类Content和GDestination被定义在了类Goods内部,并且分别有着protected和private修饰符来控制访问级别。Content代表着Goods的内容,而GDestination代表着Goods的目的地。它们分别实现了两个接口Content和Destination。在后面的main方法里,直接用 Contents c和Destination d进行操作,你甚至连这两个内部类的名字都没有看见!这样,内部类的第一个好处就体现出来了——隐藏你不想让别人知道的操作,也即封装性。
同时,我们也发现了在外部类作用范围之外得到内部类对象的第一个方法,那就是利用其外部类的方法创建并返回。上例中的cont()和dest()方法就是这么做的。那么还有没有别的方法呢?当然有,其语法格式如下:
outerObject=new outerClass(Constructor Parameters);
outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);
注意在创建非静态内部类对象时,一定要先创建起相应的外部类对象。至于原因,也就引出了我们下一个话题——
非静态内部类对象有着指向其外部类对象的引用
对刚才的例子稍作修改:
public class Goods {
[color=blue]private valueRate=2;[/color]
private class Content implements Contents {
[color=blue]private int i = 11*valueRate;[/color]
public int value() {
return i;
}
}
protected class GDestination implements Destination {
private String label;
private GDestination(String whereTo) {
label = whereTo;
}
public String readLabel() {
return label;
}
}
public Destination dest(String s) {
return new GDestination(s);
}
public Contents cont() {
return new Content();
}
}
修改的部分用蓝色显示了。在这里我们给Goods类增加了一个private成员变量valueRate,意义是货物的价值系数,在内部类Content的方法value()计算价值时把它乘上。我们发现,value()可以访问valueRate,这也是内部类的第二个好处——一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!这是一个非常有用的特性,为我们在设计时提供了更多的思路和捷径。要想实现这个功能,内部类对象就必须有指向外部类对象的引用。Java编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。
有人会问,如果内部类里的一个成员变量与外部类的一个成员变量同名,也即外部类的同名成员变量被屏蔽了,怎么办?没事,Java里用如下格式表达外部类的引用:
outerClass.this
有了它,我们就不怕这种屏蔽的情况了。
静态内部类
和普通的类一样,内部类也可以有静态的。不过和非静态内部类相比,区别就在于静态内部类没有了指向外部的引用。这实际上和C++中的嵌套类很相像了,Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用这一点上,当然从设计的角度以及以它一些细节来讲还有区别。
除此之外,在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。
局部内部类
是的,Java内部类也可以是局部的,它可以定义在一个方法甚至一个代码块之内。
public class Goods1 {
public Destination dest(String s) {
class GDestination implements Destination {
private String label;
private GDestination(String whereTo) {
label = whereTo;
}
public String readLabel() { return label; }
}
return new GDestination(s);
}
public static void main(String[] args) {
Goods1 g= new Goods1();
Destination d = g.dest("Beijing");
}
}
上面就是这样一个例子。在方法dest中我们定义了一个内部类,最后由这个方法返回这个内部类的对象。如果我们在用一个内部类的时候仅需要创建它的一个对象并创给外部,就可以这样做。当然,定义在方法中的内部类可以使设计多样化,用途绝不仅仅在这一点。
下面有一个更怪的例子:
public class Goods2{
private void internalTracking(boolean b) {
if(b) {
class TrackingSlip {
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip() { return id; }
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
}
public void track() { internalTracking(true); }
public static void main(String[] args) {
Goods2 g= new Goods2();
g.track();
}
}
你不能在if之外创建这个内部类的对象,因为这已经超出了它的作用域。不过在编译的时候,内部类TrackingSlip和其他类一样同时被编译,只不过它由它自己的作用域,超出了这个范围就无效,除此之外它和其他内部类并没有区别。
匿名内部类
java的匿名内部类的语法规则看上去有些古怪,不过如同匿名数组一样,当你只需要创建一个类的对象而且用不上它的名字时,使用内部类可以使代码看上去简洁清楚。它的语法规则是这样的:
new interfacename(){......}; 或 new superclassname(){......};
下面接着前面继续举例子:
public class Goods3 {
public Contents cont(){
return new Contents(){
private int i = 11;
public int value() {
return i;
}
};
}
}
这里方法cont()使用匿名内部类直接返回了一个实现了接口Contents的类的对象,看上去的确十分简洁。
在java的事件处理的匿名适配器中,匿名内部类被大量的使用。例如在想关闭窗口时加上这样一句代码:
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
有一点需要注意的是,匿名内部类由于没有名字,所以它没有构造函数(但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数,并在实现的过程中使用super关键字调用相应的内容)。如果你想要初始化它的成员变量,有下面几种方法:
如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为final。
将匿名内部类改造成有名字的局部内部类,这样它就可以拥有构造函数了。
在这个匿名内部类中使用初始化代码块。
为什么需要内部类?
java内部类有什么好处?为什么需要内部类?
首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能。
不过你可能要质疑,更改一下方法的不就行了吗?
的确,以此作为设计内部类的理由,实在没有说服力。
真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题——没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。
-----------------------------------------------------
原文地址:http://www.frontfree.net/view/article_704.html
分享到:
相关推荐
【北大青鸟初识Java】课程是为初学者设计的一套完整的Java编程入门教程,旨在帮助学员们建立起坚实的Java基础知识,逐步掌握这门强大的面向对象编程语言。北大青鸟作为国内知名的IT教育机构,其教学内容深受业界认可...
- **类与对象**:Java是面向对象的,以类为基本单位,通过实例化对象进行操作。 - **封装、继承和多态**:这是面向对象的三大特性,封装隐藏内部实现,继承实现代码复用,多态增加程序灵活性。 - **异常处理**:...
共分16章:第1章 初识Java,第2章 初识对象和简单,第3章运算符、表达式和语句,第4章类与对象,第5章子类与继承,第6章,第7章 数组与枚举,第8章 内部类与异常,第9章 常用实用类,第10章 输入、输出流等
本文档“初识Java”将引导我们了解Java的基础知识。 首先,我们需要理解Java的核心概念。Java是基于类的,这意味着程序是由类定义的,而类是对象的蓝图。这些对象可以包含数据(称为属性或字段)和行为(称为方法)...
在标签中提到的“源码”部分,学习Java文件操作时,查看和理解相关的API源码可以帮助深入理解其内部工作原理,提高问题解决能力。而对于“工具”,可能指的是使用IDE(如IntelliJ IDEA或Eclipse)提供的文件操作功能...
第六章:接口与内部类; 第七章:集合的应用; 第八章:异常和反射; 第九章:初识AWT和Swing; 第十章:Swing中的常用组件; 第十一章:线程; 第十二章:I/O流; 第十三章:Swing中的表格; 第十四章:桌面程序...
Java开发基础:初识Java Java,一种广泛使用的高级编程语言,由Sun Microsystems(现为Oracle Corporation的一部分)在1995年推出。它的设计目标是具有“一次编写,到处运行”的特性,使得代码能够在各种操作系统上...
Java技术文档是一个全面涵盖Java编程语言的技术资源集合,旨在帮助开发者深入理解和熟练运用Java进行软件开发。这份文档可能包括了从基础知识到高级特性的详细解释,...无论是初识Java还是寻求进阶,都能从中受益匪浅。
9. **接口与内部类**:接口是定义行为规范的工具,而内部类(包括成员内部类、局部内部类和匿名内部类)允许在类内部定义类,提供更灵活的代码组织方式。 10. **泛型**:泛型是Java 5引入的特性,用于在编译时提供...
3.8 内部类 3.9 使用Java的文档注释 第4章 面向对象(下) 4.1 类的继承 4.2 抽象类与接口 4.3 对象的多态性 4.4 异常 4.5 包 4.6 访问控制 4.7 使用jar文件 第5章 多线程 5.1 如何创建与理解线程 5.2 多线程的同步 ...
首先,JavaBean本质上是一个Java类,它必须拥有一个公共的、无参数的构造函数,这通常是编译器自动生成的默认构造函数。这个构造方法允许其他组件实例化JavaBean对象。此外,JavaBean的特性在于它提供了getter和...
《初识Java:JDK1.5入门精典》是一本专为新手设计的Java编程教程,基于Java Development Kit(JDK)1.5版本。这本书深入浅出地介绍了Java编程语言的基础概念和核心特性,旨在帮助读者快速掌握Java编程技能。 首先,...
- **初识Java** - Java的历史和发展背景 - Java的特点:平台无关性、面向对象、安全性等 - Java开发环境的搭建:JDK安装与配置 - Hello World程序编写 - **数据类型和运算符** - Java的基本数据类型(整型、...
在函数式编程方面,Java SE 6引入了匿名内部类和Lambda表达式,尽管这部分在Java 8中得到了进一步强化,但书中也会进行简单介绍。这些新特性使得Java更加简洁和高效,特别是处理集合和并发操作时。 此外,书中还...
10. **Java高级特性**:这部分可能包括泛型、枚举、匿名内部类、Lambda表达式等,这些都是Java SE 5.0及以后版本引入的新特性。 每个.ppt文件名对应一章的内容,例如“第1章.ppt”可能涵盖Java环境搭建和基本语法,...
《初识Java对象:从概念到代码》是一本面向初学者的Java编程教材,它旨在帮助读者从基础概念深入理解到实际编码。书中的内容涵盖了Java面向对象编程的核心概念,包括类、对象、继承、多态等核心特性,以及封装、抽象...
《初识Java编程解决方案》 本资料集合" Beg_Java_Solutions.rar "是为初学者设计的一套完整的Java学习解决方案,旨在帮助新手快速掌握Java编程基础,并能够解决实际编程过程中遇到的问题。通过深入理解并实践其中的...
#### 一、初识Java **1.1. Java语言是什么** Java是一种广泛使用的高级编程语言,由Sun Microsystems于1995年发布。它被设计为简单、面向对象、分布式、解释型、健壮、安全、与体系结构无关、可移植、高性能、多...
理解JVM的工作原理,包括类加载机制、内存模型(堆、栈、方法区等)、垃圾收集和性能优化,对于编写高性能的Java应用至关重要。 ### 7. RESTful RESTful是一种Web服务设计风格,强调资源和状态转移。在Java中,可以...