内部类
一.匿名内部类
匿名内部类适合创建那种只需要一次使用的类,例如前面介绍命令模式时所需要的Command对象,匿名内部类的语法有点奇怪,创建匿名内部类时会立即创建一个该类的实例,这个类的定义立即消失,匿名内部类不能重复使用。
语法格式一般如下:
//匿名类可以是实现接口 或则继承类
new 实现接口() | 父类构造器 (实参列表){
//匿名内部类的类体部分
}
从上面可以看出,匿名内部类必须继承一个父类,或者实现一个接口,但最多只能继承一个父类,或者实现一个接口。
关于匿名内部类还有如下两条规则:
-
匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义为抽象类。
-
匿名内部类不能定义构造器(Constructor),由于匿名内部类没有类名,所以无法定义构造器,但匿名构造类可以定义初始化块,可以通过实例初始化块来完成构造函数需要完成的部分。
匿名类使用示例代码:通过匿名类来初始化HashMap并且put初始化值
public class HashMapInitializeDemo {
/**
* HashMap初始化 使用匿名内部类的方式
*/
public static void initialize() {
HashMap<String,Integer> map = new HashMap<String,Integer>(){{put("a",1);put("b",2);put("c",3);}};
}
static class Num{
public Num() {
System.out.println("initialize num");
}
void put() {
System.out.println("put something");
}
}
public static void main(String[] args) {
//这是匿名内部类的写法,第一个大括号是代表类,第二个大括号代表匿名内部类的初始化代码块。 这种语法表示该匿名内部类继承了Num类,还有我们经常使用匿名内部类来作为接口的实现类,作为方法入参。
// 1.匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义为抽象类。
// 2.匿名内部类不能定义构造器(Constructor),由于匿名内部类没有类名,所以无法定义构造器,但匿名构造类可以定义初始化块,可以通过实例初始化块来完成构造函数需要完成的部分。
Num num = new Num(){{
put();}};
Num num1 = new Num() {{
System.out.println("create num");
}};
List<String> list = new LinkedList<String>(){{add("a");add("b");}};
System.out.println(list.get(0));
List<String> list1 = new LinkedListAnonymity<>();
System.out.println(list1.get(0));
}
/**
* LinkedListAnonymity
* new LinkedListAnonymity<>(); 等同于HashMapInitializeDemo中的匿名类 List<String> list = new LinkedList<String>(){{add("a");add("b");}};
* @param <T>
*/
static class LinkedListAnonymity<T> extends LinkedList<T> {
public LinkedListAnonymity() {
add((T) "a");
add((T) "b");
}
}
}
二、方法内部类
方法内部类就是定义在方法中的类。
- 方法内部类只能在定义该类的方法中使用,因此不能使用访问控制符和static修饰符。
- 方法中的内部类必须在调用之前定义。
/**
* 通过 Class 获取代理对象,模拟Spring 容器和Spring 通过JDK动态代理实现切面AOP
* 验证一个道理 想要通过动态代理实现AOP,必须要通过容器化来控制代理类的生成
* @param cl
* @return
*/
public static Girl getGirl(Class<? extends Girl> cl) {
/**
* 方法中的内部类必须在 调用之前定义
* 由于方法内部类不能在该方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。
*/
class ObjectInvocationHandler implements InvocationHandler {
Object object;
public ObjectInvocationHandler() { }
public Object wrap(Object object) {
this.object = object;
return Proxy.newProxyInstance(cl.getClassLoader(), cl.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before do something........");
Object obj = method.invoke(object, args);
System.out.println("after do something.........");
return obj;
}
}
try {
return (Girl) new ObjectInvocationHandler().wrap(cl.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}