网站首页 > java教程 正文
作者: 手艺人,
来源:公众号IT烂笔头
1
基础知识
匿名内部类大家肯定都很熟悉,如果你是做Android开发的一定再熟悉不过了,因为你学Android的时候写的第二行代码一定是setOnClickListener,第一行代码一般是findViewById。
写个简单的匿名内部类:
作为一个初级工程师,一般能使用就ok了。
匿名内部类,顾名思义就是不知道名字的内部类。它真的就没有名字吗?有想过这个问题吗?如果你想过,那证明你是一个不甘于做初级工程师,想往上拔高的人。事实上匿名内部类在被编译成字节码的时候会被定义一个类名,只是类名呢不是那么的被人类所容易阅读,假设上面那个匿名内部类的外部类为OuterClass,编译器编译后就会将上面的匿名内部类定义为:"包名.OuterClass$1",其中里面的'$1'指的是OutterClass类里面的第一个匿名内部类。如果你怀疑它的正确性,可以验证下:
Class testClass = Class.forName("包名.OuterClass$1");
System.out.println(testClass);
2
继承结构
以上面举的例子来说,匿名内部类的父类是Test,或者我们常用的setOnclickListener(new OnclickListener{})来说,就是实现OnClickListener接口的匿名内部类。
那么我们能不能同时继承一个类和实现一个接口呢?像这样:
Test|OnClickListener testListener = new Test() implements OnClickListener{
...
}
这种可以吗?在有些语言是支持的,但是呢Java是不支持的。我们知道Java10支持类型推导了,那上面的例子可不可以写成这样呢?
var testListener = new Test() implements OnClickListener{
...
}
可不可以呢?其实也是不可以的,那有同学就讲了,你在这瞎折腾了半天,都是不可以那还讲干啥?聪明的同学可能能从上面也能吸取到一些知识。比如,你可以去查一下哪些语言支持第一种方式,这里只是给你抛砖引玉用的。从第二种方式中我讲到了Java 10支持了类型推导,那你也可以再去查下Java 10到底新增了哪些新特性是不是?那到底能不能实现呢?当然是可以的,你可以使用Java的local class。感兴趣的读者自行查阅一下哦。
如果你是中级工程师掌握到这里就蛮不错的了。
3
构造方法
匿名内部的构造方法是谁定义的?很显然开发者并没有机会去定义,是由编译器给我们编译的,在非静态区里面,我们写匿名内部类时会持有外部类的引用,那这个引用编译器会帮我们作为构造方法的参数传进去。举个例子:
由于我们的内部类是非静态的所以是需要持有内部类InnerClass的外部类的实例(OuterClass的实例),而我们的匿名内部类也是在非静态的方法区中,那么就会持有匿名内部类$1的外部类的实例(Client的实例),所以编译器给我们的匿名内部类定义的构造方法中带上了两个实例的参数。
那如果我们将内部类换成Interface呢?Interface跟静态内部类的效果一样,就不会引用外部类的实例,所以这时候编译器在定义匿名内部类的构造方法时只会将匿名内部类的外部类实例带入,而不会将内部类的外部类实例带入:
如果我们将匿名内部类放在静态的方法中,那么编译器就不会将任何外部类的实例作为构造方法的参数传入了。
还有一个我们在匿名内部类访问局部变量时,需要将局部变量声明为final的。原因是什么呢?因为如果你在匿名内部类访问局部变量的时候,编译器一样会在匿名内部类的构造方法中将其作为参数传进去,不过呢,传进去的时候是当时的一个拷贝,如果不是final的,那么你的代码在后面对变量进行更改的话,那么在匿名内部类中使用的还是旧的值,这样处理显然会有问题,所以Java要求必须使用final来声明。如图:
所以,综上我们知道匿名内部类的构造方法的定义是:
- 由编译器定义
- 构造方法的参数
- 外部类的对象(定义在非静态方法区)
- 父类的外部类的对象(父类是非静态的)
- 父类的构造方法参数
- 外部捕获的变量(方法体引用的局部final变量)
到这里为止,如果你都知道的话,我觉你已经有了高工的思维高度了。
猜你喜欢
- 2024-12-10 Spock单元测试框架系列(六):Mock静态方法
- 2024-12-10 面试官:为什么java中静态方法不能调用非静态方法和变量?
- 2024-12-10 详解Java中的静态代理和动态代理
- 2024-12-10 一文讲透父子类中静态变量,成员变量初始化顺序原理
- 2024-12-10 Java错误排行:50种常见bug及如何避免它们(二)
- 2024-12-10 Java中的反射机制:动态调用方法与属性
- 2024-12-10 Java 详细剖析关键字 static,深入全面了解
- 2024-12-10 java静态方法是什么
- 2024-12-10 为何要在Java中使用静态类?
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)