• 匿名内部类的构造器


    匿名内部类的构造器

      来看一个例子:

    class A{
        public B f() {
            return new B() {
                {
                    setName("annoyInner");    //非静态初始块,等同于构造方法
                }
                //。。。
                //可以自定义成员变量、成员方法
                //可以重写父类方法
            };
        }
        public static void main(String[] args) {
            A a = new A();
            System.out.println(a.f().getName());  
        }
    }
    class B{
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public B() {
            System.out.println("B的无参构造");
        }
    }

      打印结果:

    B的无参构造
    annoyInner

      在匿名类中,可用花括号括起来进行一些必要的初始化操作,表示非静态初始化块,等同于构造方法。由于没有方法名,此构造方法不区分有参无参,那么怎么在匿名构造方法中使用参数呢?

    class A{
        public B f() {
            String name = "annoyInner";
            return new B() {
                {
                    setName(name);  //直接使用局部变量即可
                }
                //。。。
                //可以自定义成员变量、成员方法
                //可以重写父类方法
            };
        }
        public static void main(String[] args) {
            A a = new A();
            System.out.println(a.f().getName());
        }
    }
    class B{
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public B() {
            System.out.println("B的无参构造");
        }
    }

      打印结果同上。匿名类中直接使用局部变量或成员变量即可,相当于匿名类的有参构造器(Java 中局部内部类和匿名内部类访问的局部变量必须由 final 修饰,以保证内部类和外部类的数据一致性。但从 Java 8 开始,添加了 Effectively final 功能,我们可以不加 final 修饰符,由系统默认添加。详情可点击《Java8新特性之Effectively final》进行学习。

      接下来又有个问题,匿名类的构造器能不能重载呢?

      答案是不能,还是因为匿名类没有名字,连赋予参数的地方都没有,但是你可以这样写:

    class A{
        public B f() {
            return new B() {
                {
                    setName("annoyInner1");
                }
                {
                    setName("annoyInner2");
                }
                {
                    setName("annoyInner3");
                }
                //...
            };
        }
        public static void main(String[] args) {
            A a = new A();
            System.out.println(a.f().getName());
        }
    }

      打印结果是annoyInner3,这相当于是多个初始化块,会依次执行,并不是构造器的重载,但是这样写跟写在一个初始化块中没有什么区别。

      我们都知道匿名类实例化时会默认调用父类的无参构造,如何调用父类的有参构造?加上super(name)是不行的:

    class A{
        public B f() {
            return new B("annoyInner") {
                {
                    //super(name);  //编译报错
                }
            };
        }
        public static void main(String[] args) {
            A a = new A();
            System.out.println(a.f().getName());
        }
    }
    class B{
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public B() {
            System.out.println("B的无参构造");
        }
        public B(String name) {
            this.name = name;
            System.out.println("B的有参构造");
        }
    }

      打印结果如下,直接在匿名类的表达式中使用父类的有参构造即可

    B的有参构造
    annoyInner

       下面是一个很常见的匿名类的运用,经常看见有人这么写:

                 ArrayList<String> list = new ArrayList<String>() {{
                    add("A");
                    add("B");
                    add("C");
                }};
    
                Map m = new HashMap() {
                    {
                        put("name","zhangsan");
                        put("age",18);
                    }
                };

       看到这个,我只想说:

      花里胡哨!!!

      拿arrayList为例,外层的花括号创建了一个继承于ArrayList的匿名类,里层的花括号表示在这个匿名类的初始化块中调用了继承而来的add方法,实际上这个匿名类和ArrayList没有什么区别。这样写好像是简洁了一些,但是可读性也要差一些,也并不会带来多少性能上的优化,目前本人还不知道会不会引发什么问题。不过取决于个人喜好,用用也无妨。

  • 相关阅读:
    remove all event handlers from a control
    clone Control event handlers at run time
    EventHandlerList z
    code
    From delegates to lambdas z
    tpl Dataflow for net 4.0
    FlowLayoutPanel autowrapping doesn't work with autosize
    easyui radio 取值和赋值
    jquery hide和show方法
    java设计模式 工厂模式
  • 原文地址:https://www.cnblogs.com/xiaohang123/p/12080429.html
Copyright © 2020-2023  润新知