2015-05-29 116 views
1

我有一个类User,只有两个字段:ID,名称为什么这两个显然相同的对象有不同的类类型?

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类,我试图用两种不同的方法来初始化用户对象:

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()); 
    } 
} 

然后我可以得到输出

class test.Main$1 
class test.User 

有趣的是为什么u类是Main类的内部类类型?但实际上我仍然可以使用u.getId()u.getName()方法。

+1

您创建了一个匿名类。 –

+0

这就是所谓的“双大括号初始化反模式”。你刚刚发现它为什么是反模式。 –

+0

我不认为这个问题是重复的!提问者最后的句子的实际答案是关于内部类的*命名*。这些问题是相关的但不同的。 恐怕我不能添加以下内容作为答案,因为问题是关闭的,但是这里是:内部类不是'Main'类型,但只有它的名字是基于它的,因为'Main'是封闭的类型。此行为在[JLS§13.1](https://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html#jls-13.1)中指定。 – siegi

回答

6

你创建一个从User这里延伸的anonymous class

User u = new User() { //<-- this open bracket defines a new class 
     { 
      setId(1l); 
      setName("LHuang"); 
     } 
    }; 
2

User u = new User() { // here's your derived class 
     {    // here's the initialiser block 
      setId(1l); 
      setName("LHuang"); 
     } 
    }; 

用户创建一个新的匿名子(外的大括号),然后定义在这个内置的大括号内的初始化块。为了清晰起见,人们通常建议避免上述构造(并不是很多人知道它是如何工作的),并且由于您正在创建内部类,因此它将隐式引用外部类。这可能会导致垃圾收集和序列化问题。

话虽如此,我会尽量少用上述(例如,用于在单元测试等,由于其简洁建立测试集合)

+1

这不是一个* static * initalizer。它是一个普通的“实例”初始值设定项。 –

相关问题