Java 匿名类对效率的影响

发布于 2024-09-05 00:24:32 字数 805 浏览 13 评论 0原文

这两种做事方式之间的效率(例如执行时间、代码大小等)有什么区别吗?

下面是创建对象但不执行任何操作的人为示例,但我的实际场景可能是创建新线程、侦听器等。假设以下代码片段发生在循环中,以便它可能会产生影响。

使用匿名对象:

void doSomething() {
    for (/* Assume some loop */) {
        final Object obj1, obj2; // some free variables

        IWorker anonymousWorker = new IWorker() {
            doWork() {
                // do things that refer to obj1 and obj2
            }
        };
    }
}

首先定义一个类:

void doSomething() {
    for (/* Assume some loop */) {
        Object obj1, obj2;
        IWorker worker = new Worker(obj1, obj2);
    }
}

static class Worker implements IWorker {
    private Object obj1, obj2;
    public CustomObject(Object obj1, Object obj2) {/* blah blah */}

    @Override
    public void doWork() {}
};

Is there any difference in efficiency (e.g. execution time, code size, etc.) between these two ways of doing things?

Below are contrived examples that create objects and do nothing, but my actual scenarios may be creating new Threads, Listeners, etc. Assume the following pieces of code happen in a loop so that it might make a difference.

Using anonymous objects:

void doSomething() {
    for (/* Assume some loop */) {
        final Object obj1, obj2; // some free variables

        IWorker anonymousWorker = new IWorker() {
            doWork() {
                // do things that refer to obj1 and obj2
            }
        };
    }
}

Defining a class first:

void doSomething() {
    for (/* Assume some loop */) {
        Object obj1, obj2;
        IWorker worker = new Worker(obj1, obj2);
    }
}

static class Worker implements IWorker {
    private Object obj1, obj2;
    public CustomObject(Object obj1, Object obj2) {/* blah blah */}

    @Override
    public void doWork() {}
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

花间憩 2024-09-12 00:24:32

匿名类和顶级类之间唯一的实际区别是匿名类将持有对外部类的隐式引用。

这不会在性能上体现出来,但如果您序列化这些类,则会影响您。

The only practical difference between the anonymous classes and the top-level classes is that the anonymous classes will hold an implicit reference to the outer class.

This won't manifest itself in performance, but will impact you if you ever serialise these classes.

俯瞰星空 2024-09-12 00:24:32

性能差异应该很小(如果有的话)。如果有差异,也将处于不值得担心的程度。

IMO,您应该专注于编写可读和可维护的代码,并忽略“微观”性能问题,直到您根据应用程序分析有明确证据表明它们很重要。

(根据记录,当匿名内部类引用封闭范围中的 final 时,这是通过隐藏构造函数参数和隐藏实例属性在字节码级别实现的。字节码几乎是与您从其他实现中获得的字节码相同。)

There should be little if any performance difference. If there is a difference it will be at a level where it is not worth worrying about.

IMO, you should focus on writing code that is readable and maintainable, and ignore "micro" performance issues until you have clear evidence that they are significant ... based on profiling the application.

(For the record, when an anonymous inner class refers to a final in an enclosing scope, this is implemented at the bytecode level by means of hidden constructor arguments and hidden instance attributes. The bytecodes will be almost the same as the bytecodes that you get from your other implementation.)

浴红衣 2024-09-12 00:24:32

重要的是要认识到匿名类仍然是在编译时已知且完全编译的类。事实上,您正在定义一个匿名类主体,可能在循环内包含许多方法和字段等,但这并不意味着运行时必须在每次迭代时编译该类型。

因此,两种方法之间的性能差异可以忽略不计。需要考虑的重要因素是可读性、可重用性、可测试性等。

It's important to realize that anonymous classes are still classes that were known and fully-compiled at compile time. The fact that, say, you're defining an anonymous class body, perhaps with many methods and fields etc within a loop, doesn't mean that the runtime has to compile that type on every iteration.

Thus, any difference in performance between the two approaches are negligible. The important factors to consider are things like readability, reusability, testability, etc.

凑诗 2024-09-12 00:24:32

实际上,我注意到在实例化匿名类的许多实例时,性能会受到显着影响。

考虑是否可能是由于本地类是静态的,我删除了它,但没有什么区别。

就我而言,我做了 1000 个选择 3 次,即 499,500 次。具有本地类(无论是否静态)的版本花费了 26 秒,而具有功能相同的匿名类的版本花费了 2 分 20 秒。

I actually HAVE noticed a significance performance hit when instantiating many instances of an anonymous class.

Thinking if might be due to the local class being static I removed that and it made no difference.

In my case, I was doing something 1000 choose 3 times which is 499,500. The version with the local class (regardless of static or not) took 26 seconds and the version with the anonymous functionally identical class took 2 minutes 20 seconds.

埖埖迣鎅 2024-09-12 00:24:32

关于性能,您应该考虑是否应该创建内部类或根本不创建。

不良实践的一个例子如下:

public List<String> someMethod() {
       return new ArrayList<String>() {{
                      add("Item one");
                      add("Item two");
              }};
}

虽然这种语法上的便利乍一看很聪明,但这(通常被忽视)创建了一个匿名内部类,其对象保留对外部实例的引用。
由于该对象也作为 someMethod 的结果值提供给外部,因此您无法确定调用者对此列表执行的操作。
如果他将生成的 ArrayList 实例放入某个静态变量中,您当前的对象也将永远保留!

Regarding performance you should consider if an inner class should be created or not at all.

An example for bad practice is something like:

public List<String> someMethod() {
       return new ArrayList<String>() {{
                      add("Item one");
                      add("Item two");
              }};
}

While this syntactical convenience looks smart at a first glance, this (often unnoticed) creates an anonymous inner class whose object keeps a reference to the outer instance.
As this object is also given to the outside as result value of someMethod, you cannot be sure what your caller does with this list.
If he puts the resulting ArrayList instance into some static variable, your current Object will be kept forever too!

捂风挽笑 2024-09-12 00:24:32

推测代码性能是浪费时间的好方法。没有什么比实际对代码进行基准测试更好的了。如果您担心性能,请测量代码。如果您怀疑您的代码不是最佳的,请分析代码以找出时间花在哪里,然后尝试改进这些部分。此时,实际研究字节码可能是合适的,看看这是否可以给您提示哪种实现更有效。

完成此操作后,再次测量代码,以确保不会让事情变得更糟,例如使代码变得更丑陋且更难以维护。

Speculating about code performance is an excellent way of wasting your time. Nothing compares to actually benchmarking the code. If you're worried about performance, measure the code. If you suspect that your code is sub-optimal, profile the code to figure out where the time is spent, then try to improve those parts. At this time it may be appropriate to actually study the byte code to see if that may give you a hint which implementation is more efficient.

When you've done that, measure the code again to make sure that you didn't make things worse, for example by making the code uglier and more difficult to maintain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文