这个技术很少有教程来讲,但是在源码中经常出现,所以我感觉有必要单独拿出来说一说。
步骤 1 new一个匿名子类对象
我姑且叫这种情况为“匿名子类”吧,就是有这样的情况,你new一个类的时候直接加一对花括号,实际上已经创建了它的一个匿名子类。老实说,我第一次见到这种写法也是懵逼的。
比如我有一个类
public class Fu { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void eat(){ System.out.println(name + " 吃饭!"); } }
这是一个平平无奇的类,假如我们要弄个类继承Fu,然后重写eat方法,一般会这么写:
public class Zi extends Fu{ @Override public void eat() { System.out.println("这是Zi类的eat方法!"); } }
这样做当然是可以的,但是会有这样的情况,就是我们希望有个类,仅仅重写了eat方法,而且很确定不会在别的地方再使用该子类了,就可以new一个匿名子类对象:
Fu f = new Fu(){ @Override public void eat() { System.out.println("eat方法被重写了!"); } };
这样就可以省去多写一个类的麻烦。
步骤 2 匿名子类的构造器
先看一段代码
public static void main(String[] args) { Fu f = new Fu(){ /** 这里再打一个打括号,就是在匿名子类的构造器中写东西 */ { setName("Zi"); } @Override public void eat() { /** this.getClass为匿名类*/ System.out.println(this.getClass()); System.out.println(this.getName() + " eating..."); } }; f.eat(); }
这种写法也很奇特,但是真的有用!你可以在生成匿名子类对象的时候,把数据初始化一下。
步骤 3 实战应用1.给HashMap赋初值
Map<String,Object> study = new HashMap<String,Object>(){{ put("name","java小白翻身"); put("url","java18.cn"); }}; System.out.println(study);
这下是真的学到了,因为生成的对象还是Map(因为多态),所以不会有任何影响,赶紧拿去秀翻同事吧~~
步骤 4 实战应用2.给ArrayList赋初值
List<Integer> list = new ArrayList<Integer>(){{ add(1); add(2); add(3); }}; System.out.println(list);
步骤 5 实战应用3.传参的时候直接new接口
这种情况是非常普遍的!
这种情况是非常普遍的!
这种情况是非常普遍的!
重要的话说三遍,如果你喜欢翻看源码,这种技巧真的是随处可见。比如:
//直接开启一个线程 new Thread(new Runnable() { @Override public void run() { System.out.println("线程开启!"); } }).start();
一般这种情况都是直接new接口,实际上是new一个接口的匿名实现类啦,不过我一般喜欢说new一个接口。
如果这个接口中只有一个抽象方法,就可以用lamda表达式:
new Thread(() -> { System.out.println("线程开启!"); }).start();
步骤 6 神级展开: 我顺手做了个小框架?!
这部分内容是我突然想到的,既然这个匿名子类对象这么好用,我是不是可以用这个特性来做个SQL生成器?
最终做出来的效果是这样的:
String sql = new SQL(){{ select("*").from("t_user").where("uname like 'j%'") .and("sex='男'").orderby("id desc"); }}.toString(); System.out.println(sql);
很美观,很有趣是不是,其实SQL类的代码异常简单啦,相信你也一定可以写出来:
package com.javaxbfs.demo; /** 自定义简单SQL构建器,不支持复杂sql* */ public class SQL { public StringBuffer sql = new StringBuffer(); public SQL select (String targetStr){ sql.append(" select ").append(targetStr); return this; } public SQL from (String table){ sql.append(" from ").append(table); return this; } public SQL where (String where){ sql.append(" where ").append(where); return this; } public SQL and (String and){ sql.append(" and ").append(and); return this; } public SQL orderby (String orderby){ sql.append(" order by ").append(orderby); return this; } public String toString() { return sql.toString(); } }