匿名类和final外部变量的实现

我们知道,在java中有大量的匿名类使用,而且在匿名类的函数中,我们还可以使用在外部声明的final变量,例如下面的android代码:

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变量,而且还为它创建了一个隐含的构造函数。这个构造函数也是隐含调用的,由编译器自动产生。

时间: 2024-08-02 12:19:37

匿名类和final外部变量的实现的相关文章

C#:在匿名方法中捕获外部变量

先来一段代码引入主题.如果你可以直接说出代码的输出结果,说明本文不适合你.(代码引自<深入理解C#>第三版) class Program { private delegate void TestDelegate(); static void Main(string[] args) { TestDelegate[] delegates = new TestDelegate[2]; int outside = 0; for(int i = 0; i < 2; i++) { int insid

匿名函数访问外部变量有gc

直接上测试代码: using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestStructGC : MonoBehaviour { public struct StructDef { public System.Action act; public StructDef(System.Action callback) { act = callback; } } pub

解决内存泄漏更加清楚的认识到Java匿名类与外部类的关系

1.事件起因 在做项目的时候,通过Android Studio的Memory Monitor窗口观察程序内存使用情况,发现当程序退出的时候,有一部分应该释放掉的内存没有释放掉,知道程序中应该有内存泄漏了.为了发现程序中的内存泄漏,我切换了IDE工具到Eclipse,里面安装了内存泄漏的分析工具MAT,具体怎么用MAT分析内存泄漏可以自己Google,我把我自己找到内存泄漏的地方贴出来 从上图中可以看到,有24M左右的内存被mView(其实它真正是一个Fragment)这个变量持有,导致Java垃

一个注意事项:内部类引用的外部变量必须是final的

之前写过一个项目,好久没更新了,最近翻起以前的代码,发现在这里报了一个错.(现在转到Intellij了,从前在Eclipse luna中是可以编译通过的,Eclipse mars也会报错,JDK版本都是1.8,还没去查为什么) 为什么在内部类中引用外部变量时,必须声明为final呢? 最开始我想的是,会和Java的内存模型有关.因为我们都知道,带有static的变量或者方法是属于类的,也就是说,类成员是被储存在堆内存里面的.那么final是否也是这样?经过查找资料,得知:final 是保护 所修

2.匿名类,匿名类对象,private/protected/public关键字、abstract抽象类,抽象方法、final关键字的使用,多线程Thread类start方法原理

package com.bawei.multithread; //注意:模板方法我们通常使用抽象类或者抽象方法!这里我们为了方便在本类中使用就没有使用抽象类/抽象方法 public class TemplateThread { //如果这个方法不想被子类或者别人随意改动[这样子类就不能覆写该方法了],这里方法就要设置为final方法 public final void println(String message){ System.out.println("###################

内部类与匿名类(转)

Java 中的内部类和匿名类* 为什么需要内部类? Java 内部类有什么好处?为什么需要内部类? 首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口.由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能. 不过你可能要质疑,更改一下方法的不就行了吗? 的确,以此作为设计内部类的理由,实在没有说服力.真正的原因是这样的,java 中的内部类和接口

【转 Java 中的内部类和匿名类

 Java 中的内部类和匿名类 2008-10-16 13:47:41 标签:Java 内部类 匿名类 休闲 职场 Java 中的内部类和匿名类* 为什么需要内部类? Java 内部类有什么好处?为什么需要内部类? 首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口.由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能. 不过你可能要质疑,更改一

Java笔记十八.内部类和匿名类

内部类和匿名类 转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空) 一.内部类 1.定义 在一个类内部定义类,即为嵌套类(内部类).有如下几点特点:(1)嵌套类可以直接访问嵌套它的类的成员(变量和方法),包括private成员.但是,嵌套类的成员却不能被嵌套它的类直接访问.(2)内部类使得程序代码更为紧凑,程序更具模块化. 2.内部类实现方法 (1)类中定义和使用一个内部类 在类中直接定义的嵌套类的使用范围,仅限于这个类的内部.内部类的定义和普通

Java 嵌套类(Nested Class):静态嵌套类,内部类,局部类,匿名类

 将一个人比作类,人由大脑.肢体.器官等组成,而嵌套类相当于其中的某个器官,例如心脏:它也有自己的属性和行为(血液.跳动). 嵌套类(Nested Class)的结构: //外部类 class Out { private int age = 12; //嵌套类 class In { public void print() { System.out.println(age); } } } public class Demo { public static void main(String[]