在上一篇Tinking in Java的博客中笔者总结了Java中内部类的相关概念,内部类的意义,以及
内部类的分类和相关注意点。但是笔者并未就匿名内部类进行详细的阐述。现在专门做一个补充
说明。
概念
匿名内部类就是不能有名称的类,因此是没有办法去引用他们的。必须在创建的时候作为
new语句的一部分对其进行声明。这个就必须采用另一种形式的new语句:形式如下:
new <类或者接口> {类的主体},它声明的就是一个匿名内部类,对给定的类进行扩展或者实现
一个给定的接口,它创建了那个类的新实例,并将之作为结果返回。如果一个匿名类对另一个类
进行扩展,则可以访问变量,覆盖其方法,如果匿名类实现了某一个接口,则它的主体就必须
实现接口中方法。
首先看看匿名内部类到底是如何实现的吧:
package com.kiritor; public class ClassNoNameTest { public void doSomething() { new ClassNoName() { private int i = 0; }; System.out.println("这里生成了一个匿名内部类,不过需要注意的是 ClassNoName这个类必须是存在的!"); } public static void main(String[] args) { new ClassNoNameTest().doSomething(); } }这个例子感觉上还是不好理解,在举一个例子:使用过java的GUI编程的都会很快的
意识到匿名内部类的应用。这里自己来模拟一下:
package com.kiritor; /**@author Kiritor * 事件接口*/ interface EventListener { void clicked(); void pressed(); /*其他的就不多写了*/ }
package com.kiritor; public class EventAdapter implements EventListener{ @Override public void clicked() { // TODO Auto-generated method stub } public void pressed() {}; }
下面简单的模拟按钮按下的状态
package com.kiritor; /** * @author Kiritor 一个按钮 */ public class MyButton { private int flag = 0;// 0代表点击,1代表按下 public MyButton(int flag) { this.flag = flag; // TODO Auto-generated constructor stub } private void addListener() { if (flag == 0) { new EventAdapter() { @Override public void clicked() { // TODO Auto-generated method stub System.out.println("按钮被点击了"); } }.clicked(); } else { new EventAdapter() { @Override public void pressed() { // TODO Auto-generated method stub System.out.println("按钮处于按下的状态"); } }.pressed(); } } /** * 不过按钮怎么能够被点击呢?换句话说程序 怎么知道按钮何时被惦记呢? 这个是底层的了,可以使用 标志变量简单的模拟一下 */ public static void main(String[] args) { new MyButton(1).addListener(); } }Tips:外部是无法调用匿名内部类的方法的!
上面的代码中new就是建立一个EventAdapter对象,后面的{}表示这个括号中的操作作用于
这个默认的对象,后面的则是相关的方法体。
说白了上面的模拟过程就是:创建一个对象的实例,并且重写他的方法,打开EventAdapter
可以发现他实现了EventListener接口。button.addListener()方法的参数就是一个EventListener
类型的,而实际上传的是一个实现该接口的EventAdapter派生出的一个匿名类。
判断匿名内部类的存在
基本上匿名内部类的判断还是挺简单的,对于熟悉Swing的人来书,找出"匿名类"不是难事!
匿名内部类注意事项
匿名内部类的声明是在编译时进行的,实例化则是在运行时进行的。这就意味着在程序存在
循环的情况下new语句会创建相同匿名类的几个实例,而非创建几个不同匿名类的一个实例。
在使用匿名内部类的时候须注意:
● 匿名内部类是没有构造方法的
● 匿名内部类中不能定义任何的静态成员、方法和类
● 匿名内部类中不能是public,protected,private,static的
● 匿名内部类是在new后面一般实现某一接口或实现某一类
Tips:匿名内部类可以通过以下形式访问外部类成员
int a= MyButton.this.flag;//
匿名内部类作用
从上面的阐述中可以看出的是匿名内部类是当做函数的参数传递给方法的,
在这个方法中会用接口类型接受传入的匿名类,然后调用其方法,这是多态,而且
实现了回调。
呃,回调啊:找个时间了解下!