内部类学习二牛
浏阳历史网 2021-10-29 04:49:03
许多人认为内部类的语法十分复杂,尤其是匿名内部类,这与Java所一直奉行的“简单”原则相背离的,有人甚至怀疑java中加入这么一个“特征”(feature),是不是已经开始走向“灭亡”?就像许多其它语言一样走向“灭亡”?内部类是否真的有用,有没有存在的必要?我们首先来看看内部的工作原理。
先指明一点,内部类如何工作是由编译器来负责的,与java虚拟机无关,它对这个是一无所知的。仔细留意一下上篇中编译后产生的class文件,你会发现有一个class文件的名字是Court$TimerPrinter,它的基本格式是:外部类名称$内部类名称。当碰到内部类时,编译器会自动根据内部类的代码生成一个class文件并按照上述规则命名,那么编译器到底对它做了什么呢?我们可以使用Java的反射(reflection)机制来“偷窥”它,嘿嘿。具体的代码如下所示:
* Created on
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package cess;
import flect.*;
import ing.*;
/**
* @author Demon
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class ReflectionTest {
public static void main(String[] args) {
String name=\"\";
if(ngth0)
name=args[0];
else
name=owInputDialog(\"Class name (e.g. te): \");
try{
Class c1=rName(name);
Class c2=tSuperclass();
int(\"class \" + name);
if(c2!=nullc2!=ass)
int(\" extends \" + tName());
int(\"\\n{\\n\");
printConstructors(c1);
intln();
printMethods(c1);
intln();
printFields(c1);
intln(\"}\");
}
catch(ClassNotFoundException e) { intStackTrace(); }
it(0);
}
public static void printConstructors(Class c1){
Constructor[] constructors=tDeclaredConstructors();
for(int i=0;ngth;i++){
Constructor c=constructors[i];
String name =tName();
int(String(tModifiers()));
int(\" \" + name + \"(\");
Class[] paramTypes = tParameterTypes();
for(int j=0;ngth;j++){
if (j 0) int(\", \");
int(paramTypes[j].getName());
}
intln(\");\");
}
}
public static void printMethods(Class c1){
Method[] methods=tDeclaredMethods();
for(int i=0;ngth;i++){
Method m=methods[i];
String name=tName();
Class type=tReturnType();
int(String(tModifiers())+\" \"+tName()+\" \"+name+\"(\");
Class[] paramTypes=tParameterTypes();
for(int j=0;ngth;j++){
if(j0) int(\",\");
int(paramTypes[j].getName());
}
intln(\");\");
}
}
public static void printFields(Class c1){
Field fields[]=tDeclaredFields();
for(int i=0;ngth;i++){
int(String(fields[i].getModifiers()));
int(\" \");
Class type=fields[i].getType();
int(tName());
intln(\" \"+fields[i].getName()+\";\");
}
}
}
运行该程序,在对话框中输入urt$TimerPrinter,将会得到如下输出:
}
urt$TimerPrinter(urt);
public void actionPerformed(tionEvent);
final urt this$0;
}
如上所示,编译器自动为我们加上了一个域this$0,它指向一个外部类,另外自动给构造方法增加了一个Court型别参数,用来设置this$0的值,注意this$0是编译器自己合成的,不能直接引用。
既然编译器能够自动进行转化,为什么我们不直接自己进行转换,把TimerPrinter改写成普通的class呢?如下所示:
class Court
{
. . .
public void start()
{
ActionListener listener = new TimePrinter(this);
Timer t = new Timer(interval, listener);
art();
}
}
class TimePrinter implements ActionListener
{
public TimePrinter(TalkingClock clock)
{
outer = clock;
}
直到遇见了神农小顽童益益 . . .
private TalkingClock outer;
}
问题来了,我们在实现actionPerformed方法的时候要用到访问ep,但是beep是private类型的,在TimerPrinter中是不能直接访问的。这样内部类的一个优点就显示出来了:内部类能够访问其所属外部类中的私有域而其它普通的类则不行。
那么内部类是通过什么样的机制访问它所属的外部类中的私有数据的呢?联想前面讲私有域的时候,我们都是通过方法来间接访问私有域的,那么这里是不是这样的呢?我们还是对外部类Court进行一下反射,结果如下所示:
class urt
{
public urt(int, boolean);
static boolean access$0(urt);
public void start();
private int interval;
private boolean beep;
}
我们看到新增了一个方法access$0,它的返回值就是传递过来的Court对象的beep域,这样actionPerformed方法中的if(beep)就相当于if(access$0(outer)),内部类就是通过这种机制来访问外部类的私有数据。
唐山不孕不育治疗多少钱健胃消食片儿童装
教师节礼物 送复方草珊瑚含片
- 上一页:内部类学习三局部内部类覆盖
- 下一页:内部类学习五静态内部类呢
- 九龙建业拟8.17亿港元购并能杰发展
- 小猪眼睛水肿怎么治疗?小猪眼肿了怎么快速消肿?本文有好步骤
- 4.2亿元!太原又一轮消费券来了,5年初21日开抢
- 中梁控股提前注销1.5亿美元2022年8月本票
- 深圳要蒸发了?DQ海岸城新店高能来袭,掀起今夏潮cool风暴!
- 我在新疆卖拉面:180㎡年营业额500万,8个月回本
- “牛市旗手”上市浪潮涌动,两券商同日披露IPO写明,还有一大波在排队!
- 数字工商业时代,丽人丽妆以数字化创新助力品牌可持续增长
- 哈尔滨市红十字中心医院骨外科咳嗽门诊解患者咳嗽之苦
- 奥特维(688516.SH)子公司与合盛硅业(603260.SH)原为签订1.3亿元160型单晶炉买
- 投资人提问:利群股份跟利群牌香烟有关系吗
- 儿歌多多魔力公主西西 公主换装记 宝宝来帮公主换漂亮的衣服 儿歌多多 星河知识计划 智慧生活星 抖音