2

在 java 中,经常有对象仅用于包装函数并且没有自己的任何状态。例子:

class Foo {
   void foo () {
      System.out.println("foo");
   }

   static public void main(String[] arg) {
      Foo foo = new Foo();
      foo.foo();
   }
}

我想知道表达式new Foo()是否针对 C++ 中的函数指针赋值进行了优化。这似乎是一件显而易见的事情,但当我想到它时,编译器将不得不检查foo不用于同步的东西(可能还有其他东西?)。标准对此有任何说明吗?

4

6 回答 6

1

标准(即 VM 规范和 JLS)对此没有任何说明,完全取决于 VM 实现来处理优化。

所有标准指定的是一组需要观察的不变量。如果 VM 保证您所做的事情看起来像创建一个对象,然后调用一个方法,然后处理它,它就可以做它想做的事情。

尽管优化的确切方式可能会有所不同,但这种低级别的东西很少会成为瓶颈。但是由于优化是在运行时完成的,你可以合理地确定它们只有在你的代码被大量调用时才会被执行;不经常使用的代码被解释而不是编译成机器代码。(但即使这可能会从 VM 更改为 VM,并且可能取决于特定的命令行选项。)在您的情况下,可能会发生的是,在大量运行后,VM 完全内联该方法,摆脱了对象创建和方法调用。

您绝对可以“优化”您的代码的一件事是声明Foo(和foo())final。

于 2012-07-05T13:45:09.240 回答
0

据说,创建一个对象只需要大约 10 条指令。所以这是一个非常非常便宜的手术。

这里

Sun 估计大约十个机器指令的分配成本。

所以创建一个新对象几乎没有开销。如果您将所有内容都设为静态并仅将其放在一个类中,那么这可能很快就会变得混乱。

于 2012-07-05T13:43:27.907 回答
0

如果您没有任何状态,那么您可以制作这些方法static。我不认为 java 编译器会像你想的那样优化它,即使这会改变语义。如果一个对象是通过创建的,new那么把它变成别的东西会改变语义。

我认为根本没有使用函数指针赋值的概念。

于 2012-07-05T13:43:33.293 回答
0

想象一个场景,当您有大量静态辅助方法时。如果你在你想使用它们的类中实现它们,你的类会越来越大。

但是,如果您将它们写在单独的单例或静态类中,那么您只需要保存一个引用,并通过它调用方法,因此您可以在使用多个实例时节省内存。

我可能错了,但这是我首先想到的。

于 2012-07-05T13:43:55.693 回答
0

new Foo() 将创建一个新对象

在 Java 中,只有对象、数组和原语,仅此而已

于 2012-07-05T13:44:16.220 回答
0

不知道标准是怎么说的。但我认为您提到的任何优化都没有完成。为什么我认为我很确定?因为它会破坏 java.lang.Class 功能。来自 API 文档:

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。

于 2012-07-05T13:45:09.610 回答