匿名内部类详解

匿名内部类

匿名内部类就是没有名字的内部类;



注意:

匿名内部类不能定义任何静态成员、方法。

匿名内部类中的方法不能是抽象的;

匿名内部类必须实现接口或抽象父类的所有抽象方法。

匿名内部类访问的外部类成员变量或成员方法必须用static修饰;



代码:

接口

public interface Inner {
    public String say();
}

抽象类

public abstract class Inner1 implements Inner {
}

普通类

public class Inner2 implements Inner {
    public String say() {
        return "this is Inner2";
    }
}

外部类

public class Outer {

    public static String s1 = "this is s1 in Outer";
    public static String s2 = "this is s2 in Outer";
    private static String s3 = "this is s3 in Outer";

    public void method1(Inner inner) {
        System.out.println(inner.say());
    }

    private static String method2() {
        return "this is method2 in Outer";
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        // 测试1,Inner为接口
        outer.method1(new Inner() {
            String s1 = "this is s1 in Inner";

            public String say() {
                // 外部类和匿名函数类中有同名变量s1
                return s1;
            }
        });
        // 测试2,Inner1为抽象类
        outer.method1(new Inner1() {
            String s2 = "this is s2 in Inner1";

            public String say() {
                // 外部类和匿名函数类中有同名变量s2
                return Outer.s2;
            }
        });
        // 测试3,Inner2为普通类
        outer.method1(new Inner2() {
            public String say() {
                // 访问外部类私有变量s3
                return s3;
            }
        });
        // 测试4,Inner2为普通类
        outer.method1(new Inner2() {
            public String say() {
                // 访问外部类私有方法method1()
                return method2();
            }
        });
    }
}

打印:

this is s1 in Inner
this is s2 in Outer
this is s3 in Outer
this is method2 in Outer

分析:

编译后自动生成四个文件:Outer$1.class、Outer$2.class、Outer$3.class、Outer$4.class。

Outer.class反编译(属性值、方法内容略)

public class jichu.Outer {
  public static java.lang.String s1;
  public static java.lang.String s2;
  private static java.lang.String s3;
  static {};
  public jichu.Outer();
  public void method1(jichu.Inner);
  private static java.lang.String method2();
  public static void main(java.lang.String[]);
  static java.lang.String access$0();
  static java.lang.String access$1();
}

Outer$1.class反编译(经优化、调整)

class Outer$1
  implements Inner
{
  String s1 = "this is s1 in Inner";

  public String say()
  {
    return this.s1;
  }
}

Outer$2.class反编译(经优化、调整)

class Outer$2
  extends Inner1
{
  String s2 = "this is s2 in Inner1";

  public String say()
  {
    return Outer.s2;
  }
}

Outer$3.class反编译(经优化、调整)

class Outer$3
  extends Inner2
{
  public String say()
  {
    return Outer.access$0();
  }
}

Outer$4.class反编译(经优化、调整)

class Outer$4
  extends Inner2
{
  public String say()
  {
    return Outer.access$1();
  }
}

1、匿名内部类因为没有类名,可知匿名内部类不能定义构造器

2、因为在创建匿名内部类的时候,会立即创建它的实例,可知匿名内部类不能是抽象类,必须实现接口或抽象父类的所有抽象方法

3、匿名内部类会继承一个父类(有且只有一个)或实现一个接口(有且只有一个),实现父类或接口中所有抽象方法,可以改写父类中的方法,添加自定义方法。

5、当匿名内部类和外部类有同名变量(方法)时,默认访问的是匿名内部类的变量(方法),要访问外部类的变量(方法)则需要加上外部类的类名。

6、从Outer.class反编译代码中可看出自动生成了两个静态方法:access$0()和access$1(),并在测试3和测试4中通过Outer类名直接调用,这样实现了内部类对外部类私有成员变量和方法的访问。可知内部类可以访问外部类私有变量和方法



疑问

匿名内部类不能含有static的变量和方法。但是测试发现变量可以被static final修饰,为什么?

主要是因为final类型在编译期间jvm有优化,常量池会维护这些变量。虽然非静态内部类不能脱离外部类这个上下文实例化,但是常量池使得final变量脱离了类实例化这个条件,编译期间便可确定。



总结

1、匿名内部类不能定义任何静态成员、方法。

2、匿名内部类中的方法不能是抽象的;

3、匿名内部类必须实现接口或抽象父类的所有抽象方法。

4、匿名内部类不能定义构造器;

5、匿名内部类访问的外部类成员变量或成员方法必须用static修饰;

6、内部类可以访问外部类私有变量和方法。

时间: 2024-10-10 16:25:37

匿名内部类详解的相关文章

java提高篇(九)-----详解匿名内部类

摘自http://blog.csdn.net/chenssy/article/details/13170015 java提高篇(九)-----详解匿名内部类 在Java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始化匿名内部类.匿名内部类使用的形参为何要为final. 一.使用匿名内部类内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式

java提高篇(十)-----详解匿名内部类 ,形参为什么要用final

在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始化匿名内部类.匿名内部类使用的形参为何要为final. 一.使用匿名内部类内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: new 父类构造器(参数列表)|实现接口() { //匿名内部类的类体部分 } 在这里我们看到使用匿名内部类我们必须要继承一个父类或者实现一个接口,当

【转】java提高篇(十)-----详解匿名内部类

原文网址:http://www.cnblogs.com/chenssy/p/3390871.html 在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始化匿名内部类.匿名内部类使用的形参为何要为final. 一.使用匿名内部类内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: new 父类构造器(参数列表)|实现接口() {

“全栈2019”Java第一百零四章:匿名内部类与外部成员互访详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第一百零四章:匿名内部类与外部成员互访详解 下一章 "全栈2019"Java第一百零五章:匿名内部类覆盖作用域成员详解 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复"

“全栈2019”Java第一百零五章:匿名内部类覆盖作用域成员详解

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第一百零五章:匿名内部类覆盖作用域成员详解 下一章 "全栈2019"Java第一百零六章:匿名内部类与抽象类接口注意事项 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorhaf,回复&quo

Android网络请求框架AsyncHttpClient实例详解(配合JSON解析调用接口)

最近做项目要求使用到网络,想来想去选择了AsyncHttpClient框架开进行APP开发.在这里把我工作期间遇到的问题以及对AsyncHttpClient的使用经验做出相应总结,希望能对您的学习有所帮助. 首先按照惯例先来简单了解一些AsyncHttpClient网络框架的一些知识. 1.简介 Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnect,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使用android-a

Android严苛模式StrictMode使用详解

StrictMode类是Android 2.3 (API 9)引入的一个工具类,可以用来帮助开发者发现代码中的一些不规范的问题,以达到提升应用响应能力的目的.举个例子来说,如果开发者在UI线程中进行了网络操作或者文件系统的操作,而这些缓慢的操作会严重影响应用的响应能力,甚至出现ANR对话框.为了在开发中发现这些容易忽略的问题,我们使用StrictMode,系统检测出主线程违例的情况并做出相应的反应,最终帮助开发者优化和改善代码逻辑. 官网文档:http://developer.android.c

JDK中的Timer和TimerTask详解

目录结构: Timer和TimerTask 一个Timer调度的例子 如何终止Timer线程 关于cancle方式终止线程 反复执行一个任务 schedule VS. scheduleAtFixedRate 一些注意点 1. Timer和TimerTask Timer是jdk中提供的一个定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次. TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务. 2.

详解内部类

原文出处:chenssy 可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面看是非常容易理解的,无非就是在一个类的内部在定义一个类. public class OuterClass { private String name ; private int age; public String getName() { return name; } pu