一个简单的java匿名内部类,如何引用外面类的成员?
新博娱乐手机
新博娱乐手机
当前位置 : 新博娱乐手机 > 新博娱乐官方网站

一个简单的java匿名内部类,如何引用外面类的成员?

在java中,匿名内部类为什么不用使用"外部类名.this",就可以调用外部类的方法?
这是一段简单的android代码

public class MainActivity extends Activity {

    private Button btn;
    
    @Override
    protected void onCreateBundle savedInstanceState {
        super.onCreatesavedInstanceState;
        setContentViewR.layout.activity_main;
        btn = ButtonfindViewByIdR.id.btn;
        //此处声明一个匿名内部类
        btn.setOnClickListenernew OnClickListener {
            
            @Override
            public void onClickView arg0 {
                Intent intent = new     IntentMainActivity.this,Second.class;
                //在此处,startAtivity是Activity的方法
                //这么写是对的 MainActivity.this.startActivityintent;
                //为什么也可以不加MainActivity.this 这样调用?
                startActivityintent;
            }
        };
    }

这种特性完全是一种语法糖,可以使代码更加精简。要说原因,主要是因为匿名内部类和私有内部类差不多,仅仅只在当前类中使用,所以很多事情在编译时就能确定下来。当startActivity方法在匿名类和外部类中没有冲突时,编译器可以很容易地确定到底该调用哪个类的方法,这时候省略外部类.this没有任何问题。

比如下面的代码

public class AnonyNestedClass {
    public void foo {}
    
    public void bar {
        new Object {
            public void foo {}
            public void xxx {
                foo; // 这里调用的是匿名类的foo方法
                AnonyNestedClass.this.foo; // 要想调用外部类的方法必须显式指定路径
            }
        }.xxx;
    }
}

由于外部类和匿名类都定义了foo方法,所以默认调用的是匿名类的,如果希望调用外部类的话必须要显式指定调用路径。

Compiled from "MainActivity.java"
class top.ffish.myapp.MainActivity$1 implements android.view.View$OnClickListener {
  final top.ffish.myapp.MainActivity this$0;

  top.ffish.myapp.MainActivity$1top.ffish.myapp.MainActivity;
    Code:
       0: aload_0       
       1: aload_1       
       2: putfield      #1                  // Field this$0:Ltop/ffish/myapp/MainActivity;
       5: aload_0       
       6: invokespecial #2                  // Method java/lang/Object."<init>":V
       9: return        

  public void onClickandroid.view.View;
    Code:
       0: new           #3                  // class android/content/Intent
       3: dup           
       4: invokespecial #4                  // Method android/content/Intent."<init>":V
       7: astore_2      
       8: aload_0       
       9: getfield      #1                  // Field this$0:Ltop/ffish/myapp/MainActivity;
      12: aload_2       
      13: invokevirtual #5                  // Method top/ffish/myapp/MainActivity.startActivity:Landroid/content/Intent;V
      16: return        
}

如果你反编译MainActivity$1.class,可以看到这个内部类有一个this$0变量引用MainActivity对象。这个变量在构造器中被初始化2: putfield指令
也就是说,你不用显示的写MainActivity.this.startActivity,编译器帮你把这工作给做了

准确说这个问题属于继承关系,startActivityIntent intent方法属于Context类下的public方法,Activity继承自Context,自然也会拥有这个方法的使用权,而对于activity来说,这是个activity内的全局方法,只要在作用域内,都是可以直接调用的,默认就是当前activity的context即activity.this调用。

广告位

新博娱乐手机