- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我对一段代码的评论是这样的:
Iterable<String> upperCaseNames = Iterables.transform(
lowerCaseNames, new Function<String, String>() {
public String apply(String input) {
return input.toUpperCase();
}
});
那个人说每次我浏览这段代码时,我都会实例化这个匿名函数类,我宁愿在静态变量中有一个实例:
static Function<String, String> toUpperCaseFn =
new Function<String, String>() {
public String apply(String input) {
return input.toUpperCase();
}
};
...
Iterable<String> upperCaseNames =
Iterables.transform(lowerCaseNames, toUpperCaseFn);
从表面上看,这在某种程度上是有道理的;多次实例化一个类肯定会浪费内存什么的,对吧?
另一方面,人们在代码中间实例化匿名类就像没有明天一样,编译器优化它是微不足道的。
这是一个合理的担忧吗?
最佳答案
关于 Hot Spot JVM 优化的有趣事实,如果您实例化一个未在当前方法之外传递的对象,JVM 将在字节码级别执行优化。
通常,堆栈分配与公开内存模型的语言相关联,例如 C++。您不必在 C++ 中delete
堆栈变量,因为它们会在作用域退出时自动释放。这与堆分配相反,堆分配要求您在使用完指针后将其删除。
在 Hot Spot JVM 中,分析字节码以确定对象是否可以“逃离”线程。有three levels of escape :
这基本上类似于以下问题:1) 我是否将它传递给另一个方法或返回它,以及 2) 我是否将它与附加到 GC 根的某些东西相关联,例如 ClassLoader
或其他东西存储在 static
字段中?
在您的特定情况下,匿名对象将被标记为“本地转义”,这仅意味着对象上的任何锁(读取:同步
的使用)将被优化掉。 (为什么要在另一个线程中永远不会使用的东西上进行同步?)这与“无逃逸”不同,后者将在堆栈上进行分配。请务必注意,此“分配”与堆分配不同。它真正做的是在堆栈上为非转义对象内的所有变量分配空间。如果在 no-escape 对象中有 3 个字段,int
、String
和 MyObject
,那么将分配三个堆栈变量:一个 int
,一个 String
引用,和一个 MyObject
reference – MyObject
实例本身将仍然存储在堆中,除非它也被分析为“无法逃脱”。然后优化对象分配,构造函数/方法将使用本地堆栈变量而不是堆变量运行。
话虽这么说,但对我来说这听起来像是过早的优化。除非代码后来被证明速度很慢并且导致性能问题,否则您不应该做任何事情来降低它的可读性。对我来说,这段代码可读性很强,我不会管它。当然,这完全是主观的,但是“性能”不是更改代码的好理由,除非它与实际运行时间有关。通常,过早的优化会导致代码更难维护,性能优势微乎其微。
Java 8+ 和 Lambdas
如果分配匿名实例仍然困扰您,我建议您改用 Lambdas 来处理单一抽象方法 (SAM) 类型。 Lambda 评估是使用 invokedynamic
执行的,并且实现最终在第一次调用时仅创建 Lambda 的单个实例。可以找到更多详细信息in my answer here和 this answer here .对于非 SAM 类型,您仍然需要分配一个匿名实例。在大多数用例中,这里的性能影响可以忽略不计,但在我看来,这种方式更具可读性。
引用资料
关于java - 重复实例化匿名类是否浪费?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19718353/
我想知道如何考虑需要您做出某些选择才能看到最终结果的搜索系统。我说的是 select 表单,您可以在其中根据您的选择继续操作,然后您会看到结果。 下面描述了我正在谈论的一个随机示例。想象一下 Init
您好,我目前正在编写一些软件来管理我们的库存。我搜索了 2 个表 master_stock(保存每一个股票代码和描述)库存(保存库存代码、地点、数量...) 一切都很好,但这是我遇到的问题。 假设我的
我有 2 个表,我想合并其数据。id 是我的关键字段(增量且不同)。表1和表2字段说明例如:id - 名称 - 值 我想将表2的所有数据插入表1,它们有不同的数据,但在某些行中有相同的id。 所以当我
我正在努力解决汇编中的一个问题,我必须获取十六进制代码的第一个字节 (FF) 并将其复制到整个值中: 0x045893FF input 0xFFFFFFFF output 我所做的
我有 Eclipse Indigo 版本,我可以在其中运行 Java 和 C++ 项目。 但我只想使用另一个 Eclipse 来编写 C++ 项目。所以我将 eclipse(不是工作区)的源文件夹复制
This question already has answers here: What is a NullPointerException, and how do I fix it? (12个答案)
This question already has answers here: Numbering rows within groups in a data frame (8个答案) 5个月前关闭。
我知道用q记录到寄存器中,但我想知道是否可以设置一些东西来快速调用最后一个记录,就像一样。 回顾最后一个简短的编辑命令(有关 的讨论请参阅 here。)。 我知道@@,但它似乎只有在执行@z之后才起作
来自 Eclipse 并且一直习惯于复制行,发现 Xcode 没有这样的功能是很奇怪的。或者是吗? 我知道可以更改系统范围的键绑定(bind),但这不是我想要的。 最佳答案 要删除一行:Ctrl-A
假设我有一个包含元素的列表,例如[1,2,3,4,5,6,7,8]。我想创建长度为 N 的该元素的所有排列。 因此,对于N = 4,它将是[[1,1,1,1],[1,1,1,2],[1,1,2,1],
我有一个带有 JMenu 的 JFrame。当我在某些情况下添加包含图像的 JPanel 时,程序首次启动时菜单会重复。调整大小时重复的菜单消失。任何建议都非常感激。谢谢。代码如下: public c
我正在尝试查找目录中文件的重复项。 我对这个 block 有一个问题,它以文件地址作为参数: public void findFiles(ArrayList list){ HashMap hm
我知道这个问题已经发布并且已经给出了答案,但我的情况不同,因为我在单个方法上填充多个下拉列表,所以如果我点击此链接 After every postback dropdownlist items re
我正在尝试为我的日历应用程序实现重复模式。我希望它的工作方式与 Outlook 在您设置重复约会时的工作方式相同。 public async Task> ApplyReccurrencePeriod
我有一个利用 cookie 来支持准向导的应用程序(即,它是一组相互导航的页面,它们必须以特定顺序出现以进行注册)。 加载 Logon.aspx 页面时 - 默认页面 - 浏览器 cookie 看起来
我有 3 个输入,代码检查它们是否为空,如果为空,则将变量值添加到输入中。 所以我有 3 个具有值的变量: var input1text = "something here"; var input2t
根据数组的长度更改数组的每个元素的最佳方法是什么? 例如: User #1 input = "XYZVC" Expected Output = "BLABL" User #2 input = "XYZ
我在让 Algolia 正常工作时遇到了一些麻烦。我正在使用 NodeJS 并尝试在我的数据库和 Algolia 之间进行一些同步,但由于某种原因似乎随机弹出大量重复项。 如您所见,在某些情况下,会弹
遵循以下规则: expr: '(' expr ')' #exprExpr | expr ( AND expr )+ #exprAnd | expr ( OR expr )+ #exprO
我有一个布局,我想从左边进入并停留几秒钟,然后我希望它从右边离开。为此,我编写了以下代码: 这里我在布局中设置数据: private void loadDoctor(int doctorsInTheL
我是一名优秀的程序员,十分优秀!