Java匿名内部类和使用

内部类

一.匿名内部类

匿名内部类适合创建那种只需要一次使用的类,例如前面介绍命令模式时所需要的Command对象,匿名内部类的语法有点奇怪,创建匿名内部类时会立即创建一个该类的实例,这个类的定义立即消失,匿名内部类不能重复使用。

语法格式一般如下:

//匿名类可以是实现接口 或则继承类
new 实现接口() | 父类构造器 (实参列表){

  //匿名内部类的类体部分

}

从上面可以看出,匿名内部类必须继承一个父类,或者实现一个接口,但最多只能继承一个父类,或者实现一个接口。

关于匿名内部类还有如下两条规则:

  1. 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义为抽象类。

  2. 匿名内部类不能定义构造器(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;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值