Java 初始化块vs构造函数vs变量初始化
我正试图以一种我永远不会做的方式清理使用初始化blok的类的代码,我只是想知道我是否遗漏了一些信息。代码如下所示:Java 初始化块vs构造函数vs变量初始化,java,spring,hibernate,Java,Spring,Hibernate,我正试图以一种我永远不会做的方式清理使用初始化blok的类的代码,我只是想知道我是否遗漏了一些信息。代码如下所示: @Entity class MyClass extends BaseClass { @ManyToMany(fetch=FetchType.EAGER) private Set<OherClass> others; { if (others == null) others = new HashSet&l
@Entity
class MyClass extends BaseClass {
@ManyToMany(fetch=FetchType.EAGER)
private Set<OherClass> others;
{
if (others == null)
others = new HashSet<OtherClass>();
}
public MyClass(){
super();
}
//getters, setters and other stuff follows
}
@实体
类MyClass扩展了基类{
@ManyToMany(fetch=FetchType.EAGER)
私设他人;
{
如果(其他==null)
others=新的HashSet();
}
公共MyClass(){
超级();
}
//接球手、二传手和其他东西紧随其后
}
我认为没有理由更喜欢上面的代码:
@Entity
class MyClass extends BaseClass {
@ManyToMany(fetch=FetchType.EAGER)
private Set<OherClass> others = new HashSet<OtherClass>();
}
@实体
类MyClass扩展了基类{
@ManyToMany(fetch=FetchType.EAGER)
private Set others=new HashSet();
}
或者这个:
@Entity
class MyClass extends BaseClass {
@ManyToMany(fetch=FetchType.EAGER)
private Set<OherClass> others;
public MyClass(){
this.others = new HashSet<OtherClass>();
}
}
@实体
类MyClass扩展了基类{
@ManyToMany(fetch=FetchType.EAGER)
私设他人;
公共MyClass(){
this.others=new HashSet();
}
}
我问了我的大学,但他能回答的唯一问题是初始化块是如何工作的以及我已经知道的其他事情。我想知道,在序列化、反射、数据库持久性、注入或任何可能需要这些代码的异常情况下,java(即使是已经修复的旧版本)或框架(hibernate、spring)是否存在一些微妙的错误行为
private Set<OherClass> others;
{
if (others == null)
others = new HashSet<OtherClass>();
}
Hibernate确实会在对象构造上添加一些“魔力”,但它仍然需要从默认构造函数中获取一个实例。此时,所有实例初始值设定项都已运行
更一般地说,总是喜欢使用常量表达式立即初始化集合值变量,更好的是,将字段设置为final。对于代码的其余部分来说,这少了一个担忧
有了以上内容,您仍然可以选择如何填充集合,不同的构造函数会有所不同。我看到的唯一有用的地方是,当初始化
others
需要多个步骤时,如果在BaseClass
的构造函数中调用了一个方法,该方法可能会被子类(如MyClass
)覆盖,但您需要确保others
已正确初始化,因为该方法使用了该方法。听起来很复杂。我希望Java代码能更清楚地说明这一点:
public class BaseClass {
public BaseClass() {
init();
}
public void init() {
// do something...
}
}
public class MyClass extends BaseClass {
private Set<OtherClass> others;
{
others = new HashSet<OtherClass>();
others.add(new OtherClass("hallo"));
// or do more complicated stuff here
}
public MyClass() {
super(); // explicit or may also be implicit
}
@Override
public void init() {
// use initialized others!!
doSomething(this.others);
}
....
}
公共类基类{
公共基类(){
init();
}
公共void init(){
//做点什么。。。
}
}
公共类MyClass扩展了基类{
私设他人;
{
others=新的HashSet();
添加(新的OtherClass(“hallo”));
//或者在这里做更复杂的事情
}
公共MyClass(){
super();//显式或隐式
}
@凌驾
公共void init(){
//使用其他人!!
doSomething(这个,其他);
}
....
}
但是,这是一个非常非常糟糕的模式,您永远不应该在构造函数中调用非final或非private方法,因为子类可能尚未正确初始化
除此之外,
others
如果未初始化,则始终为空,您无需对此进行测试。重复:@kocko已经读过了,nut我不是问静态初始值设定项或它是如何工作的。谢谢,这也是我的想法。但那个代码太蹩脚了,我只是不确定,认为应该有一个非常愚蠢的理由这样做。或者也许我只是希望有一个理由这样编码。很好。但正如您提到的,从超类构造函数调用子类方法肯定是一种非常糟糕的做法,也是清理它的另一个原因。谢谢
public class BaseClass {
public BaseClass() {
init();
}
public void init() {
// do something...
}
}
public class MyClass extends BaseClass {
private Set<OtherClass> others;
{
others = new HashSet<OtherClass>();
others.add(new OtherClass("hallo"));
// or do more complicated stuff here
}
public MyClass() {
super(); // explicit or may also be implicit
}
@Override
public void init() {
// use initialized others!!
doSomething(this.others);
}
....
}