java

位置:IT落伍者 >> java >> 浏览文章

java的内部类和匿名类剖析


发布日期:2023年06月05日
 
java的内部类和匿名类剖析
Java 通过对Java语言规范进行修改显着简化了一些实用结构的实现在那些修改中最引人注目的就是内部类和匿名类如运用得当它们可使程序更易理解和维护本文介绍内部类和匿名类在Java代码中是如何具体工作的如何正确使用它们以及如何避免一些常见的错误 下面来看看这些特性具体是如何工作的?

非静态内部类

如果内部类没有指定static修饰符就拥有对外部类的所有成员的完全访问权限包括实例字段和方法为实现这一行为非静态内部类存储着对外部类的实例的一个隐式引用所以对一个非静态内部类进行实例化需要采用不同语法的new语句

引用内部类

内部类最自然的一种应用就是声明只在另一个类的内部使用的类或者声明与另一个类密切相关的类如清单B所示它是一个链表的简单实现由于Node类通常只在LinkedList的范围内使用所以最好将Node声明为LinkedList的一个内部类适用于类成员的访问控制修改符也适用于内部类也就是说内部类可以具有packageprotectedprivate和public访问权限它们的语义和正常的语义没有什么不同由于Node要在LinkedList的外部使用所以把它声明为public然而修饰符static具有不同的含义应用于内部类时它声明的类具有与其他类相同的语义也就是可进行实例化并像一个标准类那样使用惟一的区别就是它拥有对外部类的所有静态成员的完全访问权限清单C展示了一个简单的程序它创建一个链表并将它打印到标准输出设备

更优化的代码

内部和匿名类是Java 为我们提供的两个出色的工具它们提供了更好的封装结果就是使代码更容易理解和维护使相关的类都能存在于同一个源代码文件中(这要归功于内部类)并能避免一个程序产生大量非常小的类(这要归功于匿名类)

new

这种形式的new语句要求外部类的一个实例使内部类能在那个实例的上下文中创建注意清单A声明了几个非静态内部类并用标准的new语句在Method中实例化它们之所以能那样做是因为Method是外部类的一个实例方法所以new语句会在外部类的一个实例的上下文中隐式地执行只有在外部类的外部或者在其他对象的上下文中实例化一个非静态内部类时才需要使用修改过的语法但是非静态内部类具有一些限制尤其是它们不能声明静态初始化列表和静态成员除非是在常量字段中此外方法内部声明的内部类不能访问方法的局部变量和参数除非它们被初始化成final

匿名类

匿名类是不能有名称的类所以没办法引用它们必须在创建时作为new语句的一部分来声明它们

这就要采用另一种形式的new语句如下所示

new <类或接口> <类的主体>

这种形式的new语句声明一个新的匿名类它对一个给定的类进行扩展或者实现一个给定的接口它还创建那个类的一个新实例并把它作为语句的结果而返回要扩展的类和要实现的接口是new语句的操作数后跟匿名类的主体

如果匿名类对另一个类进行扩展它的主体可以访问类的成员覆盖它的方法等等这和其他任何标准的类都是一样的如果匿名类实现了一个接口它的主体必须实现接口的方法

注意匿名类的声明是在编译时进行的实例化在运行时进行这意味着for循环中的一个new语句会创建相同匿名类的几个实例而不是创建几个不同匿名类的一个实例

从技术上说匿名类可被视为非静态的内部类所以它们具有和方法内部声明的非静态内部类一样的权限和限制

如果要执行的任务需要一个对象但却不值得创建全新的对象(原因可能是所需的类过于简单或者是由于它只在一个方法内部使用)匿名类就显得非常有用匿名类尤其适合在Swing应用程序中快速创建事件处理程序

清单D就是一个非常简单的Swing应用程序它展示了与匿名类有关的几个概念这个例子创建了两个匿名类第一个对javaawteventWindowAdapter进行扩展并在应用程序窗口关闭时调用应用程序的onClose方法

即使onClose声明为private匿名类也能调用它因为匿名类本质上是应用程序类的一个内部类第二个匿名类实现了javaawtActionListener接口它在一个按钮被按下后关闭应用程序窗口注意匿名类可以访问本地变量frame这是由于匿名类在与frame相同的方法内部声明然而frame要被声明为final否则会生成编译错误

内部类

简单地说内部类是在另一个类的内部声明的类从Java 开始你可在一个类中声明另一个类这与声明字段和方法非常相似包装了内部类声明的类就称为外部类

实际上Java语言规范还允许你做更多的事情包括

在另一个类或者一个接口中声明一个类在另一个接口或者一个类中声明一个接口 在一个方法中声明一个类 类和接口声明可嵌套任意深度

上一篇:Java Poi 操作Excle

下一篇:Java中的位移运算符