我们知道,在java中有大量的匿名类使用,而且在匿名类的函数中,我们还可以使用在外部声明的final变量,例如下面的android代码:
我们为Button arrowTop创建了一个listner,在内部类的onClick函数中,又使用了arrowTop这个final变量。
public class ArrowPopupWindowDemo extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.arrow_popup_window);
final Button arrowTop = (Button) findViewById(R.id.arrow_top);
arrowTop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final ListPopupWindow popup = new ListPopupWindow(ArrowPopupWindowDemo.this);
popup.setAdapter(createAdapter());
popup.setAnchorView(arrowTop);
popup.setWidth(400);
popup.setModal(true);
popup.setListSelector(getResources().getDrawable(android.R.color.transparent));
popup.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
popup.dismiss();
}
});
ArrowPopupWindow popupWindow = popup.getPopupWindow();
popupWindow.setTitle(R.string.arrow_top);
popupWindow.setPositiveButton(android.R.string.ok, null);
popupWindow.setNegativeButton(android.R.string.cancel, null);
popup.show();
}
});
}
.....
}我们为Button arrowTop创建了一个listner,在内部类的onClick函数中,又使用了arrowTop这个final变量。
我们知道,内部匿名类也是一个单独独立的类,会别java编译器生成一个 <外部类名>$<N>的方式。这个例子里面,就是ArrowPopupWindowDemo$1。我们来反编译它的class,得到如下的信息
Compiled from "ArrowPopupWindowDemo.java"
class com.example.miui.widget.popupwindow.ArrowPopupWindowDemo$1 implements android.view.View$OnClickListener {
final android.widget.Button val$arrowTop;
final com.example.miui.widget.popupwindow.ArrowPopupWindowDemo this$0;
com.example.miui.widget.popupwindow.ArrowPopupWindowDemo$1(com.example.miui.widget.popupwindow.ArrowPopupWindowDemo, android.widget.Button);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:Lcom/example/miui/widget/popupwindow/ArrowPopupWindowDemo;
5: aload_0
6: aload_2
7: putfield #2 // Field val$arrowTop:Landroid/widget/Button;
10: aload_0
11: invokespecial #3 // Method java/lang/Object."<init>":()V
14: return
....
根据反编译结果可以看到,java编译生成了两个隐含的域:val$arrowTop和 this$0,对应的就是外部的final arrowTop变量和外部的this变量,而且还为它创建了一个隐含的构造函数。这个构造函数也是隐含调用的,由编译器自动产生。
本文深入探讨了Java匿名类中如何在内部类的函数中使用外部声明的final变量,并通过反编译分析展示了Java编译器如何生成对应的内部类及其构造函数。同时解释了匿名类的生成过程和隐含域的作用。
576

被折叠的 条评论
为什么被折叠?



