java莫名奇妙多了括号_关于java:我如何修复这些双括号

本问题已经有最佳答案,请猛点这里访问。

你好,我正在整理一些代码,我偶然发现了一些双括号。我意识到这是一种罪恶,我应该改正它。但是,我不知道从哪里开始。有人能帮忙吗?

private SelectItem notifyTypeItem = new SelectItem();

notifyTypeItem.setTitle("Default Notification");

notifyTypeItem.setWidth("100%");

notifyTypeItem.setValueMap(new LinkedHashMap() {{

put("0","None");

put("1","Subtle");

put("2","Intrusive");

}}

);

我意识到这是一种罪恶,我应该改正它。如果你不知道如何"修复"它,你是如何认识到这一点的?

我正在使用Intellij,它发出了一个自动警告。在问这个问题之前,我自己做了一些研究,我知道这会导致一些问题,但大多数解决方案似乎都没有涵盖这类问题。我试图运用我的知识,但似乎解决不了这个问题。@提姆

我仍然不确定如何在不理解此语法的目的的情况下识别此语法的问题。我假设你不理解这个目的,因为如果你理解了,你也会意识到将它重写为"简单"的代码是多么简单。

它不是我的系统,我仍然是编程的初学者。我仍然不确定"地图"和"哈希地图"。如果我能更好地对它们进行研究的话,我会乐意这样做,因为我总是愿意学习。@提姆

看看双大括号初始化——这可能不是一个罪恶。

一定要了解命名类和匿名内部类之间的区别,并且应该理解,"双括号"只是使用另一个Java中的某个特性的一个视觉红色鲱鱼,并且一个解决方案变得更加明显。也看看这个问题。这不是一个精确的复制品,但他妈的很接近。你应该能够直接应用课程。

@Oldcurmudgeon了解了为什么不应该使用双括号初始值设定项来很好地概述为什么它通常不是一个好主意。长话短说:内部匿名类和对Outer.this的隐式引用,以及它们可能导致的所有有趣的内存泄漏。

如果您使用Java 9或更高版本:EDCOX1,则1

为了理解如何修复它,您应该首先了解它在做什么。为此,您需要了解两件事:

匿名子类

实例初始值设定项块

如何修复它的tl;dr只是将那些put调用和初始化从setter中分离出来:

Map valueMap = new LinkedHashMap();

valueMap.put("0","None");

valueMap.put("1","Subtle");

valueMap.put("2","Intrusive");

notifyTypeItem.setValueMap(valueMap);

请继续阅读,了解正在发生的事情以及为什么这可能是一种糟糕的方法。匿名子类

匿名类通常只是一个没有名称的类。例如,您可以创建接口的匿名实例,如Runnable:

Runnable r = new Runnable() {

@Override

public void run() {

// Do something

}

};

r.run(); // Does that something

同样,您也可以创建抽象类和具体类的匿名实例。例如,创建ThreadLocal的匿名实例非常常见:

private static ThreadLocal localIsoDateFormat = new ThreadLocal() {

@Override

protected SimpleDateFormat initialValue() {

return new SimpleDateFormat("yyyy-MM-dd");

}

}

当您不需要一个完整的专用类来重写一两个方法时,这非常有用,类似于只使用一个方法创建接口的匿名实例。实例初始值设定项块

实例初始值设定项块允许您在构造函数之外执行初始值设定项。例如:

public class MyClass {

private final String s;

{

s ="My Class String";

}

public String getS() { return s; }

}

它本质上是一个构造函数的代替品,通常是不必要的,所以您很少看到它。它几乎总是可以移动到构造函数。组合它们

您的示例结合了它们。它正在创建LinkedHashMap的匿名子类,然后还使用初始化器块。更正确的格式,您的代码是:

Map map = new LinkedHashMap<>() {

{

put("0","None");

put("1","Subtle");

put("2","Intrusive");

}

};

它是LinkedHashMap的匿名实例,具有执行put调用的实例初始值设定项块。为什么不好?

出于同样的原因,您需要小心创建匿名类:对封闭类实例的引用。

匿名类因是应用程序内存泄漏的源而臭名昭著。您的代码似乎位于非static上下文中。这意味着您创建的匿名LinkedHashMap子类将隐式引用您的方法所在的类。例如,如果您的方法在MyClass中:

public class MyClass {

private SelectItem notifyTypeItem = new SelectItem();

public void foo() {

notifyTypeItem.setTitle("Default Notification");

notifyTypeItem.setWidth("100%");

notifyTypeItem.setValueMap(new LinkedHashMap() {{

put("0","None");

put("1","Subtle");

put("2","Intrusive");

}}

);

}

}

新创建的LinkedHashMap子类(MyClass$1将是"类名",如果可以这样称呼它的话)将引用封闭的MyClass实例。在某些情况下,这可能是好的。但是,如果您创建notifyTypeItem的目的是将其传递给其他对象,并丢弃MyClass实例,那么您将在应用程序中创建内存泄漏。MyClass实例将被MyClass$1实例引用,SelectItem将引用MyClass$1实例,因此在SelectItem实例不再被引用之前,MyClass实例将永远不会被垃圾收集。如果MyClass除了SelectItem之外还有其他几个引用,那么这只会增加单个MyClass实例消耗的总内存,并导致更多的内存泄漏问题。工具书类

以下是一些相关链接:

匿名类Java TRAIL(Java TRAIL,DOCS.Oracle .com)

初始化字段Java TRAIL(Java TRAIL,DOCS.Oracle .com)

Java中双括号初始化是什么?(所以问题,stackoverflow.com)

为什么不应该使用双括号初始值设定项(nish-tahir的blog post,blog.nishtahir.com)

什么时候使用(匿名)内部类才是安全的?(所以问题,stackoverflow.com)

正在传递notifyItemType,因此将删除类实例。此代码导致内存泄漏。我会继续读下去,但你已经打开了我的心扉。谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值