Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java反射运行时性能_Java_Performance_Reflection - Fatal编程技术网

Java反射运行时性能

Java反射运行时性能,java,performance,reflection,Java,Performance,Reflection,这是一项学术活动(免责声明) 我正在构建一个应用程序,它将从尽可能快的速度中获益,因为它将与其他应用程序竞争 我知道,与标准声明相比,使用反射(下面的示例)声明类将遭受巨大的惩罚 Class mDefinition = Class.forName("MySpecialClassString"); Constructor mConstructor = mDefinition.getConstructor(new Class[]{MySpecialClass.class}); myClass = (

这是一项学术活动(免责声明)

我正在构建一个应用程序,它将从尽可能快的速度中获益,因为它将与其他应用程序竞争

我知道,与标准声明相比,使用反射(下面的示例)声明类将遭受巨大的惩罚

Class mDefinition = Class.forName("MySpecialClassString");
Constructor mConstructor = mDefinition.getConstructor(new Class[]{MySpecialClass.class});
myClass = (MySpecialClass) mConstructor.newInstance(this);

但是,在声明了
myClass
之后,如果我以标准方式使用它
myClass.myMethod()
我还会受到性能问题的困扰吗,还是会像我以标准方式声明类一样

一旦类被加载,您就应该没事了。开销与检查表示类等的运行时结构有关。以标准方式调用方法应该可以,但是如果您开始按名称或签名搜索方法,这将产生额外的开销。

Chris Thompson的答案是正确的。但是,我对您的代码示例感到困惑

这将动态加载该类:

Class mDefinition = Class.forName("MySpecialClassString");
这将为您的类获得一个
构造函数
,它将该类的一个实例作为参数。还请注意,您在编译时使用
MySpecialClass.class
访问该类:

Constructor mConstructor = mDefinition.getConstructor(new Class[]{MySpecialClass.class});
这是通过将
This
传递到构造函数来实例化
MySpecialClass

myClass = (MySpecialClass) mConstructor.newInstance(this);
基于构造函数参数,这是否意味着我们处于
MySpecialClass
的实例方法中?非常困惑

编辑:这更接近我预期看到的内容:

Class<?> mDefinition = Class.forName("MySpecialClassString");

//constructor apparently takes this as argument
Class<?> constructorArgType = this.getClass(); //could be ThisClassName.class

Constructor<?> mConstructor = mDefinition.getConstructor(constructorArgType);

MySpecialInterface mySpecialInstance = (MySpecialInterface)mConstructor.newInstance(this);

无论如何,如果我在这里有误解或不正确,请告诉我。

当您第一次实例化该对象时,会有性能损失。一旦类被加载,它就如同它被正常实例化一样,不会有进一步的性能损失

更进一步说,如果使用反射调用方法,将有大约15倍的性能损失(Java中的默认值),之后JVM将重写反射调用,使其与静态编译调用完全相同。因此,一旦JVM重新编译了字节码,即使重复反射的方法调用也不会导致性能下降

有关这方面的更多信息,请参见以下两个链接:


+1同意-一次性动态查找应该不会有太大的开销。@Chris我已经运行了一些测试,您的假设是正确的。感谢您预先清理此文件。thks提供了非常详细的说明和额外的文档。在过去的几天里,事实证明它非常有用。你可能是对的,因为我现在才开始使用反射。让我很快地向你介绍一下这个系统是如何工作的。我们有三个类ClassA\u交互,ClassB\u对象和ClassC\u逻辑。。。ClassA_交互启动几个ClassB_对象并向它们提供位置。每个ClassB_对象都使用反射启动ClassC_逻辑。ClassC_逻辑与
这个
(ClassB_对象)一起馈送,因为它们必须调用存在于ClassB_对象上的函数。它可能很凌乱,但很有效。你能建议我采取另一种方法吗?感谢您花时间查看我的代码。我必须说我个人没有使用过动态类加载,这就是为什么我希望得到某人的确认。但是,我的理解是,如果您在代码中直接引用一个类,甚至在编译时可以访问它,那么动态加载它是没有意义的。但是,如果您有一个静态加载的
Foo
,它是一个抽象类或接口,并且动态加载的类扩展/实现了
Foo
,那么这是有意义的。这样,在动态加载一个类并实例化它之后,您可以将它强制转换为
Foo
,并与之交互,而无需进一步思考。当然,
Foo
需要以抽象/接口方法声明的形式知道您要对这些动态加载的类执行的所有操作。动态类加载(在我的例子中)只有一个目的,游戏是用一个有地图名称的txt文件提供的。地图是预先给定的,我们可以(应该)每个映射都有不同的策略。因此映射的名称将决定加载哪个类。这些不同的策略是否属于常见的抽象方法?另外,动态加载类的原因是什么-速度?编译时可用的类在运行时需要时才会加载。或者ese映射/行为在运行时之前不可用?
interface MySpecialInterface {
    //methods used to interface with dynamically loaded classes
}