建议39: 使用匿名类的构造函数

阅读如下代码,看看是否可以编译:

 public class Client {
public static void main(String[] args) {
List l1 = new ArrayList();
List l2 = new ArrayList(){};
List l3 = new ArrayList(){{}};
System.out.println(l1.getClass() == l2.getClass());
System.out.println(l2.getClass() == l3.getClass());
System.out.println(l1.getClass() == l3.getClass());
}
}

注意ArrayList后面的不同点:l1变量后面什么都没有,l2后面有一对{},l3后面有2对嵌套的{},这段程序能不能编译呢?若能编译,那输出是多少呢?

答案是能编译,输出的是3个false。l1很容易解释,就是声明了ArrayList的实例对象,那l2和l3代表的是什么呢?

(1)l2=new ArrayList(){}

l2代表的是一个匿名类的声明和赋值,它定义了一个继承于ArrayList的匿名类,只是没有任何的覆写方法而已,其代码类似于:

 //定义一个继承ArrayList的内部类
class Sub extends ArrayList{
}
//声明和赋值
List l2 = new Sub();

(2) l3=new ArrayList(){{}}

这个语句就有点怪了,还带了两对大括号,我们分开来解释就会明白了,这也是一个匿名类的定义,它的代码类似于:

 //定义一个继承ArrayList的内部类
class Sub extends ArrayList{
{
//初始化块
}
}
//声明和赋值
List l3 = new Sub();

看到了吧,就是多了一个初始化块而已,起到构造函数的功能。我们知道一个类肯定有一个构造函数,且构造函数的名称和类名相同,那问题来了:匿名类的构造函数是什么呢?它没有名字呀!很显然,初始化块就是它的构造函数。当然,一个类中的构造函数块可以是多个,也就是说可以出现如下代码:

 List l3 = new ArrayList(){{}{}{}{}{}}; 

上面的代码是正确无误,没有任何问题的。现在清楚了:匿名函数虽然没有名字,但也是可以有构造函数的,它用构造函数块来代替,那上面的3个输出就很清楚了:虽然父类相同,但是类还是不同的。

//===========================================================

如果说分别打印这三个类的输出结果是:

class java.util.ArrayList
class cn.summerchill.test.Client$1
class cn.summerchill.test.Client$2

[改善Java代码]使用匿名类的构造函数的更多相关文章

  1. [改善Java代码]注意Class类的特殊性

    Java语言是先把Java源文件编译成后缀为class的字节码文件,然后再通过ClassLoader机制把这些类文件加载到内存中,最后生成实例执行的,这是Java处理的基本机制,但加载到内存中的数据是 ...

  2. [改善Java代码]让工具类不可实例化

    建议42: 让工具类不可实例化 Java项目中使用的工具类非常多,比如JDK自己的工具类java.lang.Math.java.util.Collections等都是我们经常用到的.工具类的方法和属性 ...

  3. [改善Java代码]使用package-info类为包服务

    建议50: 使用package-info类为包服务 Java中有一个特殊的类:package-info类,它是专门为本包服务的,为什么说它特殊呢?主要体现在3个方面: (1)它不能随便被创建 在一般的 ...

  4. [改善Java代码]建议40:匿名类的构造函数很特殊

    建议40: 匿名类的构造函数很特殊 在上一个建议中我们讲到匿名类虽然没有名字,但可以有一个初始化块来充当构造函数,那这个构造函数是否就和普通的构造函数完全一样呢?我们来看一个例子,设计一个计算器,进行 ...

  5. [改善Java代码]不要在构造函数中抛出异常

    Java的异常机制有三种: 一.Error类以及其子类表示的是错误,它是不需要程序员处理也不能处理的异常.比如VirtualMachineError虚拟机错误,ThreadDeath线程僵尸等. 二. ...

  6. java内部类以及匿名类

    内部类 一个类内部定义的类称为内部类. 内部类允许把逻辑相关的类组织在一起,并控制内部代码的可视性. 内部类与外部类的结构层次如下. 顶层类:最外层的类 外部类:内部类所在的类 内部类:类内部定义的类 ...

  7. 2019.12.12 Java的多线程&匿名类

    Java基础(深入了解概念为主) 匿名类 定义 Java匿名类很像局部或内联系,只是没有明细.我们可以利用匿名类,同时定义并实例化一个类.只有局部类仅被使用一次时才应该这么做. 匿名类不能有显式定义的 ...

  8. Java中的匿名类

    我们知道接口一般用于定义一种规范或操作协议,然后子类实现接口的所有功能.如下面的简单代码: 定义IMessage接口 package org.lyk.entities; public interfac ...

  9. [改善Java代码]asList方法产生的List对象不可更改

    上一个建议之处了asList方法在转换基本类型数组时候存在的问题,在看下asList方法返回的列表有何特殊的地方.看代码: import java.util.Arrays; import java.u ...

随机推荐

  1. Spring4整合Hibernate4详细示例

    1. Spring整合Hibernate,主要是解决什么问题? a.让Spring提供的IOC容器来管理Hibernate的SessionFactory b.让Hibernate使用Spring提供的 ...

  2. Hibernate之QBC查询与本地SQL查询

    1. QBC查询:     QBC 查询就是通过使用Hibernate提供的QueryByCriteria API 来查询对象,这种API封装了SQL语句的动态拼装,对查询提供了更加面向对象的功能接口 ...

  3. Spring入门(3)-Spring命名空间与Bean作用域

    Spring入门(3)-Spring命名空间与Bean作用域 这篇文章主要介绍Spring的命名空间和Bean作用域 0. 目录 Spring命名空间 Bean作用域 1. Spring命名空间 在前 ...

  4. [iOS基础控件 - 6.12.3] @property属性 strong weak copy

    A.概念 @property 的修饰词   strong: 强指针/强引用(iOS6及之前是retain) weak: 弱智真/弱引用(iOS6及之前是assign)   默认情况所有指针都是强指针 ...

  5. AngularJS 学习笔记二

    AngularJS指令 指令 描述 讲解 ng_app 定义应用程序的根元素. 指令 ng_bind 绑定 HTML 元素到应用程序数据. 简介 ng_click 定义元素被单击时的行为. HTML ...

  6. Spring Data JPA Tutorial Part Nine: Conclusions(未翻译)

    This is the ninth and the last part of my Spring Data JPA tutorial. Now it is time to take a look of ...

  7. mmap和普通文件读写的区别和比较 & mmap的注意点

    参考 http://www.cnblogs.com/huxiao-tee/p/4660352.html 对linux文件系统不了解的朋友,请参阅我之前写的博文<从内核文件系统看文件读写过程> ...

  8. PsLookupProcessByProcessId分析

    本文是在讨论枚举进程的时候产生的,枚举进程有很多方法,Ring3就是ZwQuerySystemInformation(),传入SysProcessesAndThreadsInformation这个宏, ...

  9. c#与java webservice调用问题

    问题描述一: c#调用java写的websrevice,对方接收到的参数与实际传的值不一致,返回的时候值也获取不到,为null. 该参数为普通的string类型,因此不存在类型转换的问题. 处理: 使 ...

  10. Ubuntu 12.04 中安装和配置 Java JDK

    先去 Oracle下载Linux下的JDK压缩包,我下载的是jdk-7u4-linux-i586.tar.gz文件,下好后直接解压 sudo mv ./jdk1.7.0_55 /usr/lib/jdk ...