Java 通过设置静态字段为一个静态方法调用禁用if条件

Java 通过设置静态字段为一个静态方法调用禁用if条件,java,coding-style,static-methods,static-members,Java,Coding Style,Static Methods,Static Members,我们有一个类,让它命名为AttributeUpdater,在我们的项目中处理从一个实体到另一个实体的值复制。核心方法遍历实体的属性,并按照指定将它们复制到第二个实体中。在该循环期间,AttributeUpdater将所有报告(其中包含有关复制期间覆盖的值的信息)收集到一个漂亮的列表中,以便最终记录。如果值被覆盖的旧实体从未被持久化到数据库中,则会删除此列表,因为在这种情况下,您只会覆盖默认值和被视为冗余的日志记录。在伪Java代码中: public class AttributeUpdater

我们有一个类,让它命名为AttributeUpdater,在我们的项目中处理从一个实体到另一个实体的值复制。核心方法遍历实体的属性,并按照指定将它们复制到第二个实体中。在该循环期间,AttributeUpdater将所有报告(其中包含有关复制期间覆盖的值的信息)收集到一个漂亮的列表中,以便最终记录。如果值被覆盖的旧实体从未被持久化到数据库中,则会删除此列表,因为在这种情况下,您只会覆盖默认值和被视为冗余的日志记录。在伪Java代码中:

public class AttributeUpdater {
  public static CopyResult updateAttributes(Entity source, Entity target, String[] attributes) {
    List<CopyReport> reports = new ArrayList<CopyReport>();
    for(String attribute : attributes) {
          reports.add(copy(source, target, attribute));
    }
    if(target.isNotPersisted()) {
      reports.clear();
    }
    return new CopyResult(reports);
  }
}
公共类属性更新{
公共静态CopyResult UpdateAttribute(实体源、实体目标、字符串[]属性){
列表报告=新建ArrayList();
for(字符串属性:属性){
添加(复制(源、目标、属性));
}
if(target.isnotpersistend()){
报告。清除();
}
返回新的CopyResult(报告);
}
}
现在有人顿悟到,有一种情况是,即使实体还没有被持久化,报告实际上也很重要。如果我可以在方法签名中添加另一个参数,这不会有什么大不了的,但是由于类的实际结构和所需的折射量,这有点不可选择。由于该方法是静态的,所以我提出的另一个解决方案是添加一个标志作为静态字段,并在函数调用之前设置它

public class AttributeUpdater {

  public static final ThreadLocal<Boolean> isDeletionEnabled = new ThreadLocal<Boolean> {
      @Override protected Boolean initialValue() {
             return Boolean.TRUE;
      }      

  public static Boolean getDeletionEnabled() { return isDeletionEnabled.get(); }
  public static void setDeletionEnabled(Boolean b) { isDeletionEnabled.set(b); }

  public static CopyResult updateAttributes(Entity source, Entity target, String[] attributes) {
    List<CopyReport> reports = new ArrayList<CopyReport>();
    for(String attribute : attributes) {
          reports.add(copy(source, target, attribute));
    }
    if(isDeletionEnabled.get() && target.isNotPersisted()) {
      reports.clear();
    }
    return new CopyResult(reports);
  }
}
公共类属性更新{
public static final ThreadLocal isDeletionEnabled=新ThreadLocal{
@重写受保护的布尔初始值(){
返回Boolean.TRUE;
}      
公共静态布尔getDeletionEnabled(){return isDeletionEnabled.get();}
公共静态void setDeletionEnabled(布尔b){isDeletionEnabled.set(b);}
公共静态CopyResult UpdateAttribute(实体源、实体目标、字符串[]属性){
列表报告=新建ArrayList();
for(字符串属性:属性){
添加(复制(源、目标、属性));
}
if(isDeleteEnabled.get()&&target.isNotPersisted()){
报告。清除();
}
返回新的CopyResult(报告);
}
}
ThreadLocal是一个用于线程安全的容器。此解决方案在执行此任务时,至少对我来说有一个主要缺点:对于所有其他假设报告已删除的方法,现在无法保证这些报告将按预期删除。再次,折射不是一个选项。因此我提出了以下建议:

公共类属性更新{

  private static final ThreadLocal<Boolean> isDeletionEnabled = new ThreadLocal<Boolean> {
      @Override protected Boolean initialValue() {
             return Boolean.TRUE;
      }      

  public static Boolean getDeletionEnabled() { return isDeletionEnabled.get(); }
  public static void disableDeletionForNextCall() { isDeletionEnabled.set(Boolean.FALSE); }

  public static CopyResult updateAttributes(Entity source, Entity target, String[] attributes) {
    List<CopyReport> reports = new ArrayList<CopyReport>();
    for(String attribute : attributes) {
          reports.add(copy(source, target, attribute));
    }
    if(isDeletionEnabled.get() && target.isNotPersisted()) {
      reports.clear();
    }
    isDeletionEnabled.set(Boolean.TRUE);
    return new CopyResult(reports);
  }
}
private static final ThreadLocal isDeletionEnabled=new ThreadLocal{
@重写受保护的布尔初始值(){
返回Boolean.TRUE;
}      
公共静态布尔getDeletionEnabled(){return isDeletionEnabled.get();}
public static void disableDeletionForNextCall(){isDeletionEnabled.set(Boolean.FALSE);}
公共静态CopyResult UpdateAttribute(实体源、实体目标、字符串[]属性){
列表报告=新建ArrayList();
for(字符串属性:属性){
添加(复制(源、目标、属性));
}
if(isDeleteEnabled.get()&&target.isNotPersisted()){
报告。清除();
}
IsDeleteEnabled.set(布尔值.TRUE);
返回新的CopyResult(报告);
}
}
通过这种方式,我可以保证,对于旧代码,函数将始终像更改前一样工作。这种解决方案的缺点是,尤其是对于嵌套实体,我将大量访问ThreadLocal容器-通过其中一种方法调用DisableDeletitionForNextCall()进行迭代对于每个嵌套元素,由于该方法被称为lot,因此存在有效的性能问题

看伪Java源代码。第一个是旧代码,第二个和第三个是允许禁用删除的不同尝试。参数不能添加到方法签名中


是否有可能确定哪种解决方案更好,或者这仅仅是一个哲学问题?或者这个问题是否有更好的解决方案?

确定哪种解决方案在性能方面更好的明显方法是对此进行基准测试。由于这两种解决方案都访问线程局部变量至少用于读取,我怀疑至少,它们之间的差异太大了。您可以这样组合它们:

if(!isDeletionEnabled.get())
  isDeletionEnabled.set(Boolean.TRUE);
else if (target.isNotPersisted())
  reports.clear();
在这种情况下,您将获得第二种解决方案(保证重置标志)的好处,而无需进行不必要的写入


我怀疑会有多大的实际差异。如果运气好的话,HotSpot JVM会将线程局部变量编译成一些不错的本机代码,这些代码不会对性能造成太大的影响,尽管我在这方面没有实际的经验。

您见过eclipse令人敬畏的重构功能吗(这可能在其他IDE中也可用)?单击方法,点击ALT+SHIFT+C(更改方法签名)添加一个参数,您就完成了。或者在
源代码
目标代码
属性
中添加一个标志。另外,当您知道要
清除
列表时,首先不要
添加
内容。与此相比,访问/设置
线程本地
是非常便宜的。可以吗你可以将其子类化,并在子类中添加方法参数?或者,你可以实现一个与现有方法相同的新方法,只是它的行为方式与你想要的方式不同。