6.4 内部类 - 6.5 代理

6.4 内部类

内部类有以下三个特点:

  • 内部类可以访问外部类的域,包括 private
  • 内部类可以对包中的其他类隐藏
  • 当想要定义一个回调函数,并想省去大量代码时,使用匿名内部类是一个好选择
使用内部类访问对象状态

内部类的对象包含一个隐式引用,指向创建了该对象的外部类对象。因而内部类对象可以直接访问外部类对象的私有域,不需要通过公开的方法。

内部类的特殊语法规则

内部类使用外部类属性时可以加上前缀以显式指示出外部类的域例如Outer.this.head
在非静态内部类中,不允许静态方法,使用静态域必须加上 final。

内部类是否有用、必要和安全

在 javac 编译了类文件后,内部类和外部类将有不同的 class 文件。内部类 class 文件名为 OuterClass$InnerClass.class 。使用javap -private ClassName命令后可以看到内部类中多出了一个域 final OuterClass this$0 ,同时内部类的构造器会有外部类作为参数。使用命令查看外部类可以看到,其包含一个静态方法 static boolean access$000 (OuterClass)。

局部内部类

内部类可以声明在方法中,称为局部内部类,并且不能用 public private 修饰。局部内部类的作用域只局限于方法中。只有声明内部类的方法可以访问这个内部类。当内部类访问了方法的局部变量,这些局部变量将会被声明为内部类的一个 final 域。以便于在该方法结束后要调用内部类的方法时可以访问那个局部变量。

匿名内部类

当只需要使用一个内部类对象时,在新建一个对象后面跟上 { } 就可以定义一个匿名内部类。匿名类实现了或扩展了那个正被 new 的类。现在用 lambda 表达式会使匿名内部类简洁很多。

静态内部类

使用内部类只是为了将一个类隐藏在另一个类内部,内部类不需要引用外部类对象,可以将内部类声明为 static。静态内部类可以有静态域和静态方法。接口中声明的内部类,自动为 static 和 public 修饰。

6.5 代理

何时使用代理

有一个表示接口的 Class 对象,确切类型在编译时无法知道。想要构造类来实现接口,需要在程序运行时定义一个新类。代理机制主要用来解决这类问题。代理类能够实现指定接口。

创建代理对象

创建一个代理对象,需要使用 Proxy 类的 newProxyInstance 方法。该方法有三个参数。

  • 类加载器 class loader。null 表示默认。
  • Class 对象数组,每个元素都是需要实现的接口
  • 调用处理器(实现了InvocationHandler 接口的对象)
    newProxyInstance 方法创建的代理对象实现了 Class 对象数组中的接口。调用那些实现的方法实际上是去调用了调用处理器里的 invoke 方法
代理类的特性

所有代理类都扩展了 Proxy 类。一个代理类只有一个实例域,调用处理器。对于特定的类加载器和预设的一组接口,只能有一个代理类。使用同一个类加载器和接口数组调用两次 newProxyInstance 方法,只能得到同一个类的两个对象。

posted @ 2020-08-23 22:40  PotatoTed  阅读(88)  评论(0)    收藏  举报