如何理解Object.getClass()方法?

9

Java中的Object.getClass()方法文档中写道:

Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class. The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. For example, no cast is required in this code fragment:

Number n = 0; 
Class<? extends Number> c = n.getClass();

Returns: The Class object that represents the runtime class of this object.

运行时类是什么?

“返回的Class对象由static synchronized方法锁定”的含义是什么?


3
运行时的类。 - Dave Newton
为什么要投票关闭?这很清楚明白啊... - Jean-Baptiste Yunès
3个回答

12

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 是已加载的 Foo 类的 Class 实例。)

因此,当线程1进入同步块时,如果线程2尝试进入该块(或任何其他在 Foo.class 上同步的东西),它必须等待。

它不一定是对同一个方法的两次调用;我可以有两个 static synchronized 方法(m1m2),其中线程1正在调用 m1,线程2正在调用 m2,调用 m2 必须等待调用 m1 完成,因为它们都在同步到同一个实例上(FooClass 实例)。

这与 getClass() 有什么关系呢?因为同样的 Class 实例就是 Foo 实例上调用 getClass 返回的内容:

System.out.println(Foo.class == (new Foo()).getClass()); // true

1
"

运行时类

"是与对象的有效类型相关联的Class对象。这意味着如果您执行以下操作:
Object o = new String();
System.out.println(o.getClass());

由于o的实际运行时类是String,因此您将获得class java.lang.String。 您无法在编译时预测它。

至于“被同步静态方法锁定”,它确实意味着对于在ThisClass类中声明的方法:

public static synchronized foo() {
    ...
}

"...等同于:"
public static foo() {
    synchronized(ThisClass.class) {
        ...
    }
}

即,类对象用作所有同步静态方法的锁。有关同步块和锁的更多信息在这里

0

关于您的第二个问题,这意味着:

class A {}
class B extends A {
  public static synchronized void f() {}
}
...
A a = new B();
Class <? extends A> c = a.getClass();

通过反射调用c上的f()将有效地使用与B.f()相同的锁。该锁将是类对象本身。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接