Java:运行时反射还是类型自省?
Java: runtime reflection or type introspection?
下面的代码是运行时反射还是类型内省?
Class c = java.util.ArrayList.class;
String className = c.getName();
我想在编译阶段使用这个,不想在运行时使用任何资源(包括时间)。它是否使用任何运行时资源?
我会说它既是运行时反射又是类型自省。
请注意,[introspection]
标记将内省定义为:
"A capability of some object-oriented programming languages to determine the type of an object at runtime."
您也可以说您的示例使用(运行时)反射来执行类型自省。
I want to use this in the compilation phase.
可以在编译时在注解处理器中检查类型。但是,我怀疑这样做所涉及的努力是令人望而却步的。您需要能够在两个语句中发现特定模式,然后用其他内容替换这些语句。
(您是否对 class 名称查找进行了基准测试,以了解它实际花费了多少时间?我本以为这只是几纳秒。不够重要。)
两者都是,正如@StephenC 已经正确指出的那样。
针对您对 compile-time 解决方案的请求:有一个解决方案,但您需要为此实施自己的构建器。
首先,一些 standard-Java 实现:
因为实施和包含您自己的构建器可能需要做很多工作而收效甚微,这里有一个更简单的答案:class 初始化。
public class CompileTimeInit {
// option 1
static public final String ARRAYLIST_CLASS_NAME = java.util.ArrayList.class.getName();
// option 2
static public final String ARRAYLIST_CLASS_NAME_INIT_BLOCK;
static {
ARRAYLIST_CLASS_NAME_INIT_BLOCK = java.util.ArrayList.class.getName();
}
public static void main(final String[] args) {
System.out.println("1:\t" + ARRAYLIST_CLASS_NAME);
System.out.println("2:\t" + ARRAYLIST_CLASS_NAME_INIT_BLOCK);
// option 3
final Class c = java.util.ArrayList.class;
final String className = c.getName();
System.out.println("3:\t" + className);
}
}
静态初始化将在 class 初始化中花费(非常少的)时间。这是运行时的一部分,但它只会在执行的某些代码中 class 为 referenced/metnioned 时发生。此初始化只会执行一次(每个 classloader 加载 class)并且被认为非常快。
现在,真正的 compile-time 实现:
您可以像 Project Lombok 那样实现真正高级的构建器,并集成到 IDE、编译器、构建工具和平台中。查看他们的页面、顶部菜单、“安装”,查看可用的选项。
您可以编写自己的构建器并将其包含在构建周期的构建周期中。最好的方法是通过 Annotaion "Pre"-Processor.
第三种选择是编写一个完整的独立应用程序。这意味着您必须实施:
- 正在打开 .java 个源文件
- 正在扫描您的界面或注释
- 用计算出的内容替换代码
- 正在保存 .java 个源文件
- 让编译阶段继续
并将其纳入您的构建周期。这在文章 above
中也有部分描述
下面的代码是运行时反射还是类型内省?
Class c = java.util.ArrayList.class;
String className = c.getName();
我想在编译阶段使用这个,不想在运行时使用任何资源(包括时间)。它是否使用任何运行时资源?
我会说它既是运行时反射又是类型自省。
请注意,[introspection]
标记将内省定义为:
"A capability of some object-oriented programming languages to determine the type of an object at runtime."
您也可以说您的示例使用(运行时)反射来执行类型自省。
I want to use this in the compilation phase.
可以在编译时在注解处理器中检查类型。但是,我怀疑这样做所涉及的努力是令人望而却步的。您需要能够在两个语句中发现特定模式,然后用其他内容替换这些语句。
(您是否对 class 名称查找进行了基准测试,以了解它实际花费了多少时间?我本以为这只是几纳秒。不够重要。)
两者都是,正如@StephenC 已经正确指出的那样。
针对您对 compile-time 解决方案的请求:有一个解决方案,但您需要为此实施自己的构建器。
首先,一些 standard-Java 实现:
因为实施和包含您自己的构建器可能需要做很多工作而收效甚微,这里有一个更简单的答案:class 初始化。
public class CompileTimeInit {
// option 1
static public final String ARRAYLIST_CLASS_NAME = java.util.ArrayList.class.getName();
// option 2
static public final String ARRAYLIST_CLASS_NAME_INIT_BLOCK;
static {
ARRAYLIST_CLASS_NAME_INIT_BLOCK = java.util.ArrayList.class.getName();
}
public static void main(final String[] args) {
System.out.println("1:\t" + ARRAYLIST_CLASS_NAME);
System.out.println("2:\t" + ARRAYLIST_CLASS_NAME_INIT_BLOCK);
// option 3
final Class c = java.util.ArrayList.class;
final String className = c.getName();
System.out.println("3:\t" + className);
}
}
静态初始化将在 class 初始化中花费(非常少的)时间。这是运行时的一部分,但它只会在执行的某些代码中 class 为 referenced/metnioned 时发生。此初始化只会执行一次(每个 classloader 加载 class)并且被认为非常快。
现在,真正的 compile-time 实现:
您可以像 Project Lombok 那样实现真正高级的构建器,并集成到 IDE、编译器、构建工具和平台中。查看他们的页面、顶部菜单、“安装”,查看可用的选项。
您可以编写自己的构建器并将其包含在构建周期的构建周期中。最好的方法是通过 Annotaion "Pre"-Processor.
第三种选择是编写一个完整的独立应用程序。这意味着您必须实施:
- 正在打开 .java 个源文件
- 正在扫描您的界面或注释
- 用计算出的内容替换代码
- 正在保存 .java 个源文件
- 让编译阶段继续
并将其纳入您的构建周期。这在文章 above
中也有部分描述