Java:双括号初始化 /匿名内部类初始化法
偶然见到一种初始化方式,感到十分新奇:
//新建一个列表并赋初值A、B、C
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
还有其他集合比如HashMap的初始化:
Map map = new HashMap() {{
put("Name", "Unmi");
put("QQ", "1125535");
}};
这种方式比起先new出对象,再一条条add,显得更加简洁和优雅。一开始没想通什么原理,后来查了一下才知道这种方法被称为双大括号初始化(double brace initialization)或者匿名内部类初始化法,实际上是一种取巧的方式。
理解:
这里以ArrayList的例子解释,首先第一层花括号定义了一个继承于ArrayList的匿名内部类 (Anonymous Inner Class):
//定义了一个继承于ArrayList的类,它没有名字
new ArrayList<String>(){
//在这里对这个类进行具体定义
};
第二层花括号实际上是这个匿名内部类实例初始化块 (Instance Initializer Block)(或称为非静态初始化块):
new ArrayList<String>(){
{
//这里是实例初始化块,可以直接调用父类的非私有方法或访问非私有成员
}
};
我们通过new得到这个ArrayList的子类的实例并向上转型为ArrayList的引用:
ArrayList<String> list = new ArrayList<String>() {{}};
- 我们得到的实际上是一个ArrayList的子类的引用,虽然这个子类相比ArrayList并没有任何功能上的改变。
- 可以认为这是个本身装有数据的子类(因为它的数据来自于自身的初始化),而不是取得引用后再赋值。
下面自定义一个类并使用这种方式初始化:
class Person{
protected String name;
protected int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
...
public static void main(String[] args) {
Person p = new Person(){
{
name = "xiaoming"; //或者调用setName()
age = 3; //或者setAge()
}
};
System.out.println(p.getName() + p.getAge());
}
注意:
(1)这种方法一定程度上使代码更简洁,但同时可能降低可读性;还可能会造成内存泄露,在序列化时可能也会出现一些问题(未测试)。
(2)当我们想构造一个数组列表,并将它传递到一个方法时,最初的写法如下:
ArrayList<String> friends=new ArrayList<>();
friends.add("tom");
friends.add("lin");
invite(friends);
如果不想要写这个数组列表,可将其作为一个匿名列表,通过双括号的方式为列表添加元素,这样代码更为简洁。
invite(new ArrayList<String> ()
{
{
add("tom");
add("lin");
}
})
外层“{}”创建了ArrayLIst的一个匿名子类,内层“{}”创建了一个对象构造块。
Java:双括号初始化 /匿名内部类初始化法的更多相关文章
- Java map双括号初始化方式的问题
关于Java双括号的初始化凡是确实很方便,特别是在常量文件中,无可替代.如下所示: Map map = new HashMap() { { put("Name", "Un ...
- Java技巧之双括弧初始化
由于Java语言的集合框架中(collections, 如list, map, set等)没有提供任何简便的语法结构,这使得在建立常量集合时的工作非常繁索.每次建立时我们都要做: 定义一个临时的集合类 ...
- ng1中 如何用双向绑定 实现单向绑定的初始时不显示双括号效果?
ng1中 如何用双向绑定 实现单向绑定(ng-bind就可以不显示{{}})的初始时不显示双括号效果? AngularJS 实例 页面加载时防止应用闪烁: <div ng-app="& ...
- Java 中 HashMap 初始化时赋值
1.HashMap 初始化的文艺写法 HashMap 是一种常用的数据结构,一般用来做数据字典或者 Hash 查找的容器.普通青年一般会这么初始化:HashMap<String, Strin ...
- java在hashmap初始化时赋初值
Java中的HashMap是一种常用的数据结构,一般用来做数据字典或者Hash查找的容器. 一般我们初始化并赋初值是这样做的: HashMap<String, Object> map = ...
- 永远不要使用双花括号初始化实例,否则就会OOM!
生活中的尴尬无处不在,有时候你只是想简单的装一把,但某些"老同志"总是在不经意之间,给你无情的一脚,踹得你简直无法呼吸. 但谁让咱年轻呢?吃亏要趁早,前路会更好. 喝了这口温热的鸡 ...
- Java类的初始化与实例对象的初始化
Java对象初始化详解 2013/04/10 · 开发 · 1 评论· java 分享到:43 与<YII框架>不得不说的故事—扩展篇 sass进阶篇 Spring事务管理 Android ...
- Java面向对象之初始化块
目录 Java面向对象之初始化块 普通初始化块 静态初始化块 初始化块与构造器 Java面向对象之初始化块 在程序设计中,让数据域正确地执行初始化一直是一个亘古不变的真理. 那么,有哪些手段可以初始化 ...
- java基础之:匿名内部类
在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以 了解到匿名内部类的使用.匿名内部类要注意的事项.如何初 ...
随机推荐
- MATLAB中多行注释以及取消的快捷键
多行注释:Ctrl+R 取消注释:Ctrl +T
- 使用EasyWechat快速开发微信支付
前期准备: 申请微信支付后, 会收到2个参数, 商户id,和商户key.注意,这2个参数,不要和微信的参数混淆.微信参数: appid, appkey, token支付参数: merchant_id( ...
- How to customize the console applicaton
下面是如何最大化console和改变其显示的字体颜色的代码,顺便包含了计时代码(帮助做性能分析): class Program { [DllImport("kernel32.dll" ...
- 第10天:CSS初始化操作
在写页面过程中,每个浏览器都会有默认样式,为了避免浏览器的样式兼容问题,我们会在样式开始部分对常用标签进行重置样式.这样我们在写样式时,就不会有误差.常用的CSS标签初始化如下: @charset & ...
- [js高手之路] 设计模式系列课程 - jQuery的链式调用与灵活的构造函数
一.我们从一个简单的构造函数+原型程序开始 var G = function(){}; G.prototype = { length : 5, size : function(){ return th ...
- 【Win10】刷新DNS缓存
释放IP配置信息 C:\Users\zheng>ipconfig /release 刷新DNS C:\Users\zheng>ipconfig /flushdns
- return 的返回值与结束功能
前言:大家好~我是阿飞~在js中return是很重要的基础.一定要彻底掌握理解它哦.否则js学习到中后期很容易懵逼的+_+ 什么是return? 1.在js中return是一个表达式语句,如果后面什么 ...
- 如何利用Jmeter做代理录制脚本
如果对于这个Jmeter不太会使用的童鞋,可以去参考其他的教学文档,本文只提供Jmeter的代理使用. 第一步:添加线程组
- 启动tomcat错误:Address already in use: JVM_Bind:8081
解决方法: 1.打开任务管理器,关闭掉javaw进程. 2.修改tomcat端口:tomcat/conf/server.xml
- [js高手之路]node js系列课程-创建简易web服务器与文件读写
web服务器至少有以下几个特点: 1.24小时不停止的工作,也就是说这个进程要常驻在内存中 2.24小时在某一端口监听,如: http://localhost:8080, www服务器默认端口80 3 ...