反复实例化一个匿名类是浪费吗? [英] Is repeatedly instantiating an anonymous class wasteful?

查看:176
本文介绍了反复实例化一个匿名类是浪费吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对以下风格的代码进行了评论:

I had a remark about a piece of code in the style of:

Iterable<String> upperCaseNames = Iterables.transform(
    lowerCaseNames, new Function<String, String>() {
        public String apply(String input) {
            return input.toUpperCase();
        }
    });

这个人说每次我查看这段代码,我都会实例化这个匿名的Function类,那个我宁愿在一个静态变量中有一个实例:

The person said that every time I go through this code, I instantiate this anonymous Function class, and that I should rather have a single instance in, say, a static variable:

static Function<String, String> toUpperCaseFn =
    new Function<String, String>() {
        public String apply(String input) {
            return input.toUpperCase();
        }
    };
...
Iterable<String> upperCaseNames =
    Iterables.transform(lowerCaseNames, toUpperCaseFn);

在一个非常肤浅的层面上,这在某种程度上是有道理的;多次实例化一个类必须浪费内存或其他东西,对吗?

On a very superficial level, this somehow makes sense; instantiating a class multiple times has to waste memory or something, right?

另一方面,人们在代码中间实例化匿名类,就像没有明天一样,它对于编译器来说,优化它是微不足道的。

On the other hand, people instantiate anonymous classes in middle of the code like there's no tomorrow, and it would be trivial for the compiler to optimize this away.

这是一个有效的问题吗?

Is this a valid concern?

推荐答案

有关Sun / Oracle JVM优化的有趣事实,如果您实例化一个未在该线程之外传递的对象, JVM将在堆栈而不是堆上创建对象。

Fun fact about Sun/Oracle JVM optimizations, if you instantiate an object that isn't passed outside of the thread, the JVM will create the object on the stack instead of the heap.

通常,堆栈分配与暴露内存模型的语言相关联,如C ++。您不必在C ++中使用 delete 堆栈变量,因为在退出作用域时它们会自动释放。这与堆分配相反,堆分配需要您在完成它时删除指针。

Usually, stack allocation is associated with languages that expose the memory model, like C++. You don't have to delete stack variables in C++ because they're automatically deallocated when the scope is exited. This is contrary to heap allocation, which requires you to delete the pointer when you're done with it.

在Sun / Oracle JVM中,分析字节码以决定如果一个对象可以逃避该线程。有三级逃生

In the Sun/Oracle JVM, the bytecode is analyzed to decide if an object can "escape" the thread. There are three levels of escape:


  1. 无转义 - 对象仅在创建它的方法/范围内使用,并且无法在外部访问对象线程。

  2. 本地/ Arg转义 - 对象由创建它的方法返回或传递给它调用的方法,但当前堆栈跟踪中的方法都不会放该对象可以在线程外部访问。

  3. 全局转义 - 将对象放在可以在另一个线程中访问的位置。

这基本上类似于问题,1)我传递/返回它,2)我是否将它与GC根目录相关联?在您的特定情况下,匿名对象将被标记为没有本地转义并将被分配到堆栈,然后通过在<$的每次迭代时弹出堆栈来清理c $ c> for 循环,所以清理它会非常快。抱歉,当我写完答案时,我并没有太多关注。它实际上是本地转义,这意味着对象上的任何锁(读取:使用 synchronized )都将被优化掉。 (为什么要同步一些不会在另一个线程中使用的东西?)这与无法逃避不同,在堆栈上进行分配。值得注意的是,这种分配与堆分配不同。它真正做的是为堆栈中的非转义对象内的所有变量分配空间。如果你有3个字段, int 字符串 MyObject 在no-escape对象中,将分配三个堆栈变量: int String 引用,以及一个 MyObject 参考。然后优化对象分配,构造函数/方法将使用本地堆栈变量而不是堆变量运行。

This basically is analogous to the questions, 1) do I pass/return it, and 2) do I associate it with something attached to a GC root? In your particular case, the anonymous object will be tagged as "no local escape" and will be allocated to the stack, then cleaned up by simply popping the stack on each iteration of the for loop, so cleaning it up will be super-fast. Sorry, I wasn't paying much attention when I wrote up my answer. It's actually local escape, which only means that any locks (read: use of synchronized) on the object will be optimized away. (Why synchronize on something that won't ever be used in another thread?) This is different from "no escape", which will do allocation on the stack. It's important to note that this "allocation" isn't the same as heap allocation. What it really does is allocates space on the stack for all the variables inside the non-escaping object. If you have 3 fields, int, String, and MyObject inside the no-escape object, then three stack variables will be allocated: an int, a String reference, and a MyObject reference. The object allocation is then optimized away and constructors/methods will run using the local stack variables instead of heap variables.

话虽如此,这对我来说听起来像是过早的优化。除非后来证明代码很慢并且导致性能问题,否则您不应该做任何事情来降低其可读性。对我来说,这段代码非常易读,我会不管它。当然,这是完全主观的,但性能并不是改变代码的好理由,除非它与算法运行时间有关。通常,过早优化是中级编码器的指标。 专家(如果有这样的事情)只需编写更容易维护的代码。

That being said, it sounds like premature optimization to me. Unless the code is later proven to be slow and is causing performance problems, you shouldn't do anything to reduce its readability. To me, this code is pretty readable, I'd leave it alone. This is totally subjective, of course, but "performance" is not a good reason to change code unless it has something to do with its algorithmic running time. Usually, premature optimization is an indicator of an intermediate-level coder. "Experts" (if there is such a thing) just write code that's easier to maintain.

这篇关于反复实例化一个匿名类是浪费吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆