The Java Object.getClass()
method javadoc说:
返回此
Object
的运行时类。返回的Class
对象是 由static synchronized
方法锁定的对象 代表班级。实际结果类型为Class<? extends |X|>
其中|X|
是表达式的静态类型的擦除 调用getClass
。例如,此代码中不需要强制转换 片段:Number n = 0; Class<? extends Number> c = n.getClass();
返回:表示此运行时类的
Class
对象 对象
什么是运行时类?
&#34;返回Class
对象...被static synchronized
方法&#34;锁定了什么?意思?
答案 0 :(得分:6)
getClass
为您提供运行时实际类的Class
实例,而不是您拥有的引用类型。
一个简单的例子可能会澄清。假设我们有一个方法接受任何实现List
并转储其类名的内容;
static void foo(List l) {
System.out.println(l.getClass().getName());
}
我们可以使用各种不同类型的列表来调用它:
foo(new LinkedList()); // Outputs "java.util.LinkedList"
foo(new ArrayList()); // Outputs "java.util.ArrayList"
由于可以使用任何foo
调用List
,因此在罕见的(!)情况下,它是不可避免的,它可以使用getClass
来确定实例的实际类别给出。
如何理解返回的Class对象是否被静态同步方法锁定?
static synchronized
方法在Class
的实例上同步,该实例表示在运行时加载的类,因此对这些方法的调用不能重叠。假设我有一个类Foo
,使用静态方法notThreadSafe
,我有两个线程需要调用它:
// On thread 1
Foo.notThreadSafe();
// On thread 2
Foo.notThreadSafe();
因为它不是线程安全的,notThreadSafe
将被声明为synchronized
:
public static synchronized void notThreadSafe() {
/* ... */
}
实际上与
相同public static void notThreadSafe() {
synchronized (Foo.class) {
/* ... */
}
}
(Foo.class
是加载的Class
类的Foo
实例。)
因此,当线程1进入同步块时,如果线程2尝试进入该块(或Foo.class
上同步的任何其他块),则必须等待。
它不必是对同一方法的两次调用;我可以有两个static synchronized
方法(m1
和m2
),其中线程1正在调用m1
而线程2正在调用m2
,并且调用{ {1}}必须等待m2
的调用完成,因为它们都在同一个实例(m1
的{{1}}实例)上进行同步。
这与Class
有何关系?因为同一个Foo
实例是getClass()
实例上Class
返回的内容:
getClass
答案 1 :(得分:1)
&#34;运行时类&#34;是与对象的有效类型关联的Class对象。这意味着如果你这样做:
Object o = new String();
System.out.println(o.getClass());
您将获得class java.lang.String
,因为o
的实际运行时类为String
。你无法在编译时预测这一点。
对于&#34;由同步静态方法&#34;锁定,它实际上意味着,对于在类ThisClass
内声明的方法:
public static synchronized foo() {
...
}
......相当于:
public static foo() {
synchronized(ThisClass.class) {
...
}
}
也就是说,Class对象用作所有同步静态方法的锁。有关同步块和锁here的更多信息。
答案 2 :(得分:0)
对于你的第二个问题意味着:
class A {}
class B extends A {
public static synchronized void f() {}
}
...
A a = new B();
Class <? extends A> c = a.getClass();
在f()
上调用c
(仅可通过反射)将有效地使用与B.f()
相同的锁定。锁将是类对象本身。