例如:
Class c = String.class;
上面的语句将变量c分配给对象,如果是这种情况,为什么当类名称像对象一样起作用时,为什么我们将classname.class称为“文字”呢?
答案 0 :(得分:1)
根据Javadoc for java.lang.Class
:
类没有公共构造函数。取而代之的是,Java虚拟机会在加载类时以及通过调用类加载器中的defineClass方法自动构造Class对象。
此外,如果您阅读Javadoc,您会发现Class
没有公开任何公共的setter变异方法。
因此Class
的实例不遵循实例化对象的通常周期,并且在大多数情况下无法进行修改。因此,String.class
的行为比普通的Java对象更像是文字值。
答案 1 :(得分:1)
文字是一种特殊的语法,编译器直接将其理解为值,而不是使用某些操作来产生该值。相对于String.CASE_INSENSITIVE_ORDER
,String.class
无法访问String
类对象的属性-它是String
类对象的。您可以在反汇编中看到它:
class Test {
public static Class classProperty = Test.class;
public static String stringProperty = "foo";
public static void main(String args[]) {
String a = "bar";
String b = Test.stringProperty;
Class x = Test.class;
Class y = Test.classProperty;
}
}
编译为:
class Test {
public static java.lang.Class classProperty;
public static java.lang.String stringProperty;
Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String bar
2: astore_1
3: getstatic #3 // Field stringProperty:Ljava/lang/String;
6: astore_2
7: ldc #4 // class Test
9: astore_3
10: getstatic #5 // Field classProperty:Ljava/lang/Class;
13: astore 4
15: return
static {};
Code:
0: ldc #4 // class Test
2: putstatic #5 // Field classProperty:Ljava/lang/Class;
5: ldc #6 // String foo
7: putstatic #3 // Field stringProperty:Ljava/lang/String;
10: return
}
在这里,您可以看到Test.stringProperty
和Test.classProperty
充当属性访问器(使用getstatic
),而Test.class
和"bar"
被当作文字(使用ldc
,“加载常数”直接加载其值)。
最后,“文字”不是与“对象”相对,而是“非文字”-评估值。 Java中“对象”的反义词是“原始”。这两个是完全独立的轴。以下是一些示例:
1
-原始文字(特别是int
)"foo"
-对象文字(特别是String
)3 - 2
-一种原始的非文字形式(尽管这是一个简单的情况,因此编译器将对其进行预先计算并将其视为文字1
)"fo" + "o"
-非文字对象(同上,编译器会将其优化为文字"foo"
)x + y
(假设x
和y
为int
)-基本的非文字(无法优化)x + y
(假设x
和y
为String
)-一个非文字对象(无法优化)。类似
Test.class
-对象文字(特别是类Class
的对象)new Test().getClass()
-非文字对象(具体是Class
类的对象)