匿名类内部类匿名内部类-转
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了匿名类内部类匿名内部类-转相关的知识,希望对你有一定的参考价值。
http://xdwangiflytek.iteye.com/blog/1340872 原文地址
前端时间在写.net项目中,一直错将.cs里的两个class当作内部类,原来是一个文件里的两个类而已,这让我想起了Java中的内部类,比较内部类,那么还有两个类,那就是匿名类和匿名内部类。今天我想就Java中的这三种类进行个比较。
我们知道在Java语言规范中可以做很多事,例如一个类或一个接口中可以声明一个类或接口,在一个方法中可以声明一个类,类与接口声明可以嵌套任意深度等。
匿名类:
1、new <类或接口><类的主体>,匿名类的声明是在编译时进行的,实例化是在运行时进行的,所以在for循环中一个new语句会创建相同匿名类的几个实例,而不是创建几个不同匿名类的一个实例。
2、如果要执行的对象需要一个对象,但却不值得创建全新的对象(可能是因为该对象只在一个方法内部使用),在这个时候使用匿名类就会非常合适,所以说,匿名类一般会在swing程序中快速创建事件处理程序。
- firstButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- getTxtValue().setText("第一个按钮触发的事件!");
- }
- });
3、从技术上说,匿名类可以被看作非静态的内部类,所以他们具有方法内部声明的非静态内部类相同的权限和限制。
内部类:
内部类顾名思义就是在一个类的内部还有一个类
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class InnerClassDemo {
- public static void main(String[] args) {
- new Outer().fun();
- }
- }
- class Outer {
- private String name = "Hello 内部类";
- class Inner {
- public void print() {
- System.out.println("name = " + name);
- }
- };
- public void fun() {
- new Inner().print();
- }
- }
内部类生成的.class文件名为:Outer$Inner.class,从上面的结构发现内部类的的缺点是“结构非常的混乱”。
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class InnerClassDemo02 {
- public static void main(String[] args) {
- new Outer02().fun();
- }
- }
- class Outer02 {
- private String name = "Hello 内部类";
- public void fun() {
- new Inner02(this).print();
- }
- public String getName() {
- return this.name;
- }
- };
- class Inner02 {
- private Outer02 out;
- public Inner02(Outer02 out) {
- this.out = out;
- }
- public void print() {
- System.out.println("name = " + this.out.getName());
- }
- };
从上可以看出内部类的优点是“可以方便的访问外部类中的私有成员”;
如果要在外部直接使用内部类的实例化对象:
外部类.内部类 内部类对象 = 外部类实例.new 内部类实例();
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class InnerClassDemo03 {
- public static void main(String[] args) {
- Outer03 out = new Outer03();//外部类实例
- Outer03.Inner inner = out.new Inner();//实例化内部类对象
- inner.print();
- }
- }
- class Outer03{
- private String name = "Hello 内部类";
- class Inner {
- public void print() {
- System.out.println("name = " + name);
- }
- }
- }
一个内部类如果使用static关键字声明的话,则此内部类就将成为外部类,可以直接通过外部类.内部类的形式访问
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class InnerClassDemo04 {
- public static void main(String[] args) {
- Outer04.Inner inner = new Outer04.Inner();// 实例化内部类对象
- inner.print();
- }
- }
- class Outer04 {
- private static String name = "Hello 内部类";
- static class Inner {
- public void print() {
- System.out.println("name = " + name);
- }
- }
- }
内部类可以在任意的地方使用,例如方法中声明
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class InnerClassDemo05 {
- public static void main(String[] args) {
- new Outer05().fun();
- }
- }
- class Outer05 {
- private static String name = "Hello 内部类";
- public void fun() {
- class Inner {
- public void print() {
- System.out.println("name = " + name);
- }
- }
- new Inner().print();
- }
- }
在方法中定义的内部类,可以直接访问外部类中的各个成员,但是如果要访问方法中的参数,则需要在参数上加上final关键字声明;
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class InnerClassDemo06 {
- public static void main(String[] args) {
- new Outer06().fun(20);
- }
- }
- class Outer06 {
- private static String name = "Hello 内部类";
- public void fun(final int temp) {
- class Inner {
- public void print() {
- System.out.println("temp = " + temp);
- System.out.println("name = " + name);
- }
- }
- new Inner().print();
- }
- }
匿名类与内部的联系与区别:
按所在位置可以分为两大类:
1、在类的方法中
特点:
a、可以访问宿主类的所有元素 ;
b、保存宿主类对象的引用,创建对象时必须有宿主类对象;
c、 不能有静态数据;
继续划分:
A、本地内部类;
B、匿名内部类
两者的区别在于本地内部类有构造方法,而匿名内部类只能实例初始化;
2、在类或接口作用域中;
继续划分:
A、普通内部类
B、静态内部类
匿名内部类:
匿名内部类是在抽象类和接口的基础之上发展起来的。
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class NoNameClass01 {
- public static void main(String[] args) {
- new X().fun2();
- }
- }
- interface A {
- public void fun();
- }
- class B implements A {
- public void fun() {
- System.out.println("Hello 准备匿名内部类");
- }
- }
- class X {
- public void fun1(A a) {
- a.fun();
- }
- public void fun2() {
- this.fun1(new B());
- }
- }
通过上面的Demo,如果现在假设B类只使用一次,那么还有必要将其定义成一个单独的类么?
呵呵,此时就可以使用匿名内部类:
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class NoNameClass02 {
- public static void main(String[] args) {
- new XX().fun2();
- }
- }
- interface AA {
- public void fun();
- }
- class XX {
- public void fun1(AA a) {
- a.fun();
- }
- public void fun2() {
- this.fun1(new AA() {
- public void fun() {
- System.out.println("Hello 准备匿名内部类");
- }
- });
- }
- }
其实在真正的项目开发中匿名内部类使用的非常之少,一般在Java的图形界面和现在的android中使用的比较多点。
最后给一个内部类实现的简单链表:
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:[email protected]
- */
- public class LinkDemo {
- public static void main(String args[]) {
- Link link = new Link();
- link.add("A");
- link.add("B");
- link.add("C");
- link.add("D");
- link.add("E");
- link.print();
- }
- };
- class Link {
- class Node {
- private String name;
- private Node next; // 单向链表,每个节点指向下一个节点
- public Node(String name) {
- this.name = name; // 通过构造方法为name属性赋值
- }
- public void addNode(Node newNode) { // 增加节点
- if (this.next == null) {
- this.next = newNode; // 保存节点
- } else {
- this.next.addNode(newNode); // 继续向下查找
- }
- }
- public void printNode() { // 输出节点
- System.out.println(this.name);
- if (this.next != null) { // 此节点之后还存在其他的节点
- this.next.printNode();
- }
- }
- };
- private Node root; // 链表的头
- public void add(String name) { // 增加节点
- Node newNode = new Node(name); // 定义一个新的节点
- /*
- * 如果是第一个节点,则肯定是根节点, 如果是第二个节点,则肯定放在根节点next中 如果是第三个节点,则肯定放在第二个节点的next中
- */
- if (this.root == null) {
- this.root = newNode; // 将第一个节点设置成根节点
- } else {
- // 肯定要放在最后一个节点之后
- // 通过节点.next来不断的判断
- this.root.addNode(newNode);
- }
- }
- public void print() {
- if (this.root != null) { // 如果根节点为空了,则没有任何内容
- this.root.printNode();
- }
- }
- };
以上是关于匿名类内部类匿名内部类-转的主要内容,如果未能解决你的问题,请参考以下文章