Java是否保证Object.getClass()== Object.getClass()?

我在这里确实是指身份平等。

例如,以下总是会打印真实的

System.out.println("foo".getClass() == "fum".getClass()); 

是的,类令牌是唯一的(对于任何给定的类加载器,就是这样)。

也就是说,您将始终在相同的类加载器领域中获取同一物理对象的引用。 然而,不同的类加载器会加载一个不同的类标记,以及由两个不同的类加载器加载时相同的类定义被认为是不同的。

看到我以前的回答这个示范。

对于X类的两个实例,

 x1.getClass() == x2.getClass() 

除非

 x1.getClass().getClassLoader() == x2.getClass().getClassLoader() 

注意: Class.getClassLoader()可能返回null,这意味着引导类加载器。

是。

返回的Class对象是被表示类的静态同步方法locking的对象。

如果有可能返回多个实例,那么

 public static synchronized void doSomething() {..} 

不会是线程安全的。

正如JVM规范中所述,它是按类加载器保证的:

首先,Java虚拟机确定是否已经logging了L是由N表示的类或接口的启动加载器。如果是,则该创build尝试是无效的,并且加载会引发LinkageError。

也就是说,如果一个类加载器(L)试图绕过默认的Class实例caching,并且让JVM不止一次地为相同的类名(N)加载byte[]定义,那么JVM就会抛出LinkageError

例如,每次调用loadClass(...)defineClass(...)实现一个调用defineClass(...)的类加载器(绕过默认caching):

 public class ClassloaderTest { private static final byte[] CLASS_DEF = readClassBytes(); private static byte[] readClassBytes() { try { InputStream is = ClassloaderTest.class.getResourceAsStream("ClassloaderTest.class"); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[16384]; while ((nRead = is.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); return buffer.toByteArray(); } catch (IOException ex) { throw new AssertionError(); } } private static ClassLoader createNonCachingClassloader() { return new ClassLoader() { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (name.equals("classloader.ClassloaderTest")) { return defineClass(name, CLASS_DEF, 0, CLASS_DEF.length); } else { return getParent().loadClass(name); } } }; } public static void main(String[] args) throws Exception { ClassLoader cl = createNonCachingClassloader(); Class<?> cl1 = cl.loadClass("classloader.ClassloaderTest"); Class<?> cl2 = cl.loadClass("classloader.ClassloaderTest"); System.out.println(cl1==cl2); } } 

这是发生了什么事情:

 Exception in thread "main" java.lang.LinkageError: loader (instance of classloader/ClassloaderTest$1): attempted duplicate class definition for name: "classloader/ClassloaderTest" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:760) at java.lang.ClassLoader.defineClass(ClassLoader.java:642) at classloader.ClassloaderTest$1.loadClass(ClassloaderTest.java:53) at classloader.ClassloaderTest.main(ClassloaderTest.java:64) 

干杯