以编程方式确定java实例的编译类型
假设我有一个扩展java.lang.Object的类,如下所示:以编程方式确定java实例的编译类型,java,static-typing,runtime-type,Java,Static Typing,Runtime Type,假设我有一个扩展java.lang.Object的类,如下所示: package pack; public class Person { } System.out.println("One runtime-type : " + one.getClass()); System.out.println("Two runtime-type : " + two.getClass()); System.out.println("Three runtime-type : " + three.getC
package pack;
public class Person {
}
System.out.println("One runtime-type : " + one.getClass());
System.out.println("Two runtime-type : " + two.getClass());
System.out.println("Three runtime-type : " + three.getClass());
以及以下三种情况:
Object one = new Object();
Object two = new Person();
Person three = new Person();
为了确定运行时类型,我只需要在实例上调用getClass()方法,如下所示:
package pack;
public class Person {
}
System.out.println("One runtime-type : " + one.getClass());
System.out.println("Two runtime-type : " + two.getClass());
System.out.println("Three runtime-type : " + three.getClass());
哪些产出:
One runtime-type : class java.lang.Object
Two runtime-type : class pack.Person
Three runtime-type : class pack.Person
现在我的问题是,如何通过编程确定上述实例的静态/编译类型
静态/编译类型指的是“左边”类型。它将输出:
One compile-type : class java.lang.Object
Two compile-type : class java.lang.Object
Three compile-type : class pack.Person
您没有指定何时查找编译时类型。从示例输出中,我假设您希望在运行时打印出编译时类型
这是不可能的(更新:),除非您事先知道要使用的所有类型,然后手动执行此操作
如果您知道您将只使用Object和Person类,那么可以尝试下面的代码。您需要为每个使用的类定义一个方法,并且编译器足够聪明,可以使用最佳匹配方法
public class Program {
static class Person {
}
public static void main(String[] params) throws Exception {
Object one = new Object();
Object two = new Person();
Person three = new Person();
System.out.println("One compile-type : " + getStaticType(one));
System.out.println("Two compile-type : " + getStaticType(two));
System.out.println("Three compile-type : " + getStaticType(three));
}
public static Class getStaticType(Person p) {
return Person.class;
}
public static Class getStaticType(Object o) {
return Object.class;
}
}
这将打印出:
One compile-type : class java.lang.Object
Two compile-type : class java.lang.Object
Three compile-type : class Program$Person
请注意,如果要将此方法应用于接口,则此方法可能会中断,在这种情况下,编译器可能无法决定使用哪种方法
原始答复: 您基本上是在询问源代码中变量的类型。在运行时,源代码只剩下Java编译器生成的字节码。这个字节码不包含任何关于变量类型的信息 以下是源代码的字节码:
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: new #2 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: astore_1
8: new #3 // class Program$Person
11: dup
12: invokespecial #4 // Method Program$Person."<init>":()V
15: astore_2
16: new #3 // class Program$Person
19: dup
20: invokespecial #4 // Method Program$Person."<init>":()V
23: astore_3
24: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
27: new #6 // class java/lang/StringBuilder
30: dup
31: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V
34: ldc #8 // String Two runtime-type :
36: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
39: aload_2
40: invokevirtual #10 // Method java/lang/Object.getClass:()Ljava/lang/Class;
43: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
46: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
49: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
52: return
}
publicstaticvoidmain(java.lang.String[])抛出java.lang.Exception;
代码:
0:new#2//类java/lang/Object
3:dup
4:invokespecial#1//方法java/lang/Object。“:()V
7:astore_1
8:新#3//班级计划$Person
11:dup
12:invokespecial#4//方法程序$Person.“:()V
15:astore_2
16:新#3//班级计划$Person
19:dup
20:invokespecial#4//方法程序$Person.“:()V
23:astore_3
24:getstatic#5//fieldjava/lang/System.out:Ljava/io/PrintStream;
27:new#6//class java/lang/StringBuilder
30:dup
31:invokespecial#7//方法java/lang/StringBuilder。“”:()V
34:ldc#8//字符串二运行时类型:
36:invokevirtual#9//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
39:aload_2
40:invokevirtual#10//方法java/lang/Object.getClass:()Ljava/lang/Class;
43:invokevirtual#11//方法java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
46:invokevirtual#12//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
49:invokevirtual#13//方法java/io/PrintStream.println:(Ljava/lang/String;)V
52:返回
}
您可以看到,除了调用Person的构造函数外,没有对Person类型的引用,因此Person类型的变量
three
等信息丢失。此外,Java没有任何内置运算符,您可以在编译时使用它来捕获变量的类型。问题的可能副本:您能提供您希望为此调用的方法的方法签名吗?您的用例是什么?这可能仅适用于泛型类型、方法参数或对象属性。所有这些都可以通过Java反射API或多或少地提取出来。真的很有趣。。。在哪里可以找到关于理解/阅读字节码的参考/文档?我认为这可能是一个很好的起点。