Why do these two apparently identical objects have different class types?
我有一个类User,只有两个字段:id,name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package test;
public class User {
private Long id ;
private String name ;
public Long getId () {
return id ;
}
public void setId (Long id ) {
this. id = id ;
}
public String getName () {
return name ;
}
public void setName (String name ) {
this. name = name ;
}
} |
然后在Main类中,我尝试使用两种不同的方法初始化User对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package test;
/**
* @author lhuang
*/
public class Main {
public static void main (String[] args ) {
User u = new User () {
{
setId (1l );
setName ("LHuang");
}
};
System. out. println(u. getClass());
User u2 = new User ();
u2. setId(1l );
u2. setName("LHuang");
System. out. println(u2. getClass());
}
} |
然后我可以得到输出
1 2
| class test.Main$1
class test.User |
有趣的是为什么u类是Main的内部类类型? 但实际上我仍然可以使用u.getId()和u.getName()方法。
-
您创建了一个匿名类。
-
这就是所谓的"双支撑初始化反模式"。 你刚刚发现了为什么它是一种反模式。
-
我不认为这个问题是重复的! 提问者最后句子的实际答案是关于内部类的命名。 问题是相关但不同的。 我担心我无法添加以下内容作为答案,因为问题已关闭,但这里是:内部类不是Main类型,但只有它的名称基于它,因为Main是封闭类型。 此行为在JLS§13.1中指定。
您正在创建一个从User扩展的匿名类:
1 2 3 4 5 6
| User u = new User() { //<-- this open bracket defines a new class
{
setId(1l);
setName("LHuang");
}
}; |
这个
1 2 3 4 5 6
| User u = new User() { // here's your derived class
{ // here's the initialiser block
setId(1l);
setName("LHuang");
}
}; |
创建一个新的匿名子类User(外部大括号),然后在其中定义一个初始化块(内部大括号)。
为了清楚起见,通常建议避免使用上述结构(没有多少人知道它是如何工作的),并且因为你正在创建一个内部类,所以它将隐含引用外部类。 这可能会导致垃圾回收和序列化问题。
话虽如此,我会谨慎使用上述内容(例如,由于其简洁性,在单元测试等中设置测试集合)
-
那不是静态初始化器。 它是一个普通的"实例"初始化器。