博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java匿名内部类
阅读量:7120 次
发布时间:2019-06-28

本文共 4178 字,大约阅读时间需要 13 分钟。

hot3.png

Java匿名内部类

前边一篇文章对匿名内部类做了一个简单的了解,。

这篇文章来深入的了解一下匿名内部类的使用

Java匿名类中的this

java的匿名类特性,在于可以在项目里“内联”地实现一个类型,它可以继承一个现有的具体或抽象类,或是实现接口,并提供完整的成员实现。例如,这里有个抽象类,定义了一个抽象方法:

// Javaabstract class MyAbstractClass {    String getName() {        return "MyAbstractClass";    }    abstract void print();}

然后我们在另一个地方使用一个匿名类,继承这个类:

// Javaclass MyClass {    String getName() {        return "MyClass";    }    MyAbstractClass someMethod() {        return new MyAbstractClass() {            public void print() {                System.out.println(getName());            }        };    }}

好,现在提一个问题,运行下面这行代码会打印出什么结果?

// Javanew MyClass().someMethod().print();

输出结果是MyAbstractClass而不是MyClass。换句话说,匿名类型中调用的getName方法是定义在MyAbstractClass里的,而不是定义在词法作用域(Lexical Scope)里的getName方法。根据Java规范,匿名类中的this(包括上面代码中“隐式”的this)表示类型本身对象,而与上下文无关。如果要访问词法作用域里的getName方法(即MyClass的方法),则反而必须显式指定MyClass类 ,例如:

// Javaclass MyClass {    String getName() {        return "MyClass";    }    MyAbstractClass someMethod() {        return new MyAbstractClass() {            public void print() {                System.out.println(MyClass.this.getName());            }        };    }}

匿名内部类定义属性字段

如下是匿名内部类的例子,

package com.usoft.java;/** */public interface CallBack {    void call();}
package com.usoft.java;/** * @author: Lenovo(2015-08-09 16:00) */public class Test {    private final Integer c = 12;    private Integer a;    private Integer b;    public Test(Integer a, Integer b) {        this.a = a;        this.b = b;    }    public static void main(String args[]) {        Test test = new Test(1, 2);        test.test(true);    }    public void hello(CallBack back) {        back.call();    }    public void test(final boolean flag) {        System.out.println("test");        hello(new CallBack() {            private Integer ia = a;            private Integer ib = b;            @Override            public void call() {                System.out.println("callback");                if (flag)                    System.out.println(ia + ib + c);                else                    System.out.println(ia + ib + c + 1);            }        });    }}

匿名内部类虽然说是匿名,但编译后也是有名字的。看一下匿名内部类的反编译结果,类的名字是 Test$1,和普通的类没有什么区别。

C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft\java>javap -p Test$1.classCompiled from "Test.java"class com.usoft.java.Test$1 implements com.usoft.java.CallBack {  private java.lang.Integer ia;  private java.lang.Integer ib;  final boolean val$flag;  final com.usoft.java.Test this$0;  com.usoft.java.Test$1(com.usoft.java.Test, boolean);  public void call();}

在匿名内部类中定义了两个属性 ia 和 ib,ia 和 ib 的初始化和赋值是在匿名内部类的构造函数中完成的,值是外部类中a 和 b。在匿名内部类中使用了外部的变量 flag。

其中初始化和赋值 ia 和 ib的时候更明显和更好理解的写法是,

public void test(final boolean flag) {    System.out.println("test");    hello(new CallBack() {        private Integer ia = Test.this.a;        private Integer ib = Test.this.b;        @Override        public void call() {            System.out.println("callback");            if (flag)                System.out.println(ia + ib + c);            else                System.out.println(ia + ib + c + 1);        }    });}

运行结果,

test

callback

15

匿名内部类的初始化

由于匿名内部类没有构造函数(通过反编译你可以知道是有构造函数的),那么怎么初始化匿名内部类,下面是一种方法,

public void test(final boolean flag) {    System.out.println("test");    hello(new CallBack() {        private Integer ia = Test.this.a;        private Integer ib = Test.this.b;        {            ia = 3;            ib = 4;        }        @Override        public void call() {            System.out.println("callback");            if (flag)                System.out.println(ia + ib + c);            else                System.out.println(ia + ib + c + 1);        }    });}

通过代码块,可以初始化类的属性,打印的结果为 19;

为什么使用final

通过上面的反编译结果,我们可以看到,内部类的构造函数(字节码层面)中有一个外部类参数,同时内部类中有一个外部类的引用,当使用外部类的属性时,是通过外部类的引用得到的相应的属性值。如果外部类的属性引用改变,那么内部类和外部类状态就不统一了。所以为了状态的统一,规定所有的外部类的属性为final定义,即不可改变的引用。

private final Integer c = 12; // 必须为final

匿名内部类的使用总结

  1. 使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。

  2. 匿名内部类中是不能定义构造函数的。

  3. 匿名内部类中不能存在任何的静态成员变量和静态方法。

  4. 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。

  5. 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

参考引用:

=================END=================

转载于:https://my.oschina.net/xinxingegeya/blog/490892

你可能感兴趣的文章
BroadcastReceiver广播
查看>>
BIOS基础知识(上)
查看>>
python pip安装+easy_install
查看>>
rsync通过服务同步、linux系统日志、screen工具
查看>>
我的友情链接
查看>>
解决HP t5335z瘦客户机休眠问题
查看>>
citrix xendesktop edition
查看>>
CentOS添加永久静态路由
查看>>
前端重构实践(一) —— 性能优化
查看>>
Oracle 10g 问题集锦
查看>>
如何处理IE首页被篡改的问题
查看>>
思科网络设备模拟器GNS3与SecureCRT关联
查看>>
Activemq判断队列存活脚本(一)
查看>>
系统状态检测 及进程控制
查看>>
xen-tools创建虚拟机找不到root fs的解决办法
查看>>
IBM X3650 M4 服务器
查看>>
备份和归档的区别
查看>>
shell基础
查看>>
linux 文件类型 时间戳 ls bash特性四 文件查看命令 cp move echo
查看>>
如何在XenDesktop中映射USB设备
查看>>