可能重复:
Does Java guarantee that Object.getClass() == Object.getClass()?
我注意到Eclipse为equals
生成了这段代码:
public class MyClass {
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyClass other = (MyClass) obj;
// ...
}
}
特别感兴趣的是这段代码:
if (getClass() != obj.getClass())
return false;
代码假定Class
返回的getClass()
对象将所有对象的相同的实例(而不仅仅是等效的实例)同一类。也就是说,他们认为没有必要这样写:
if (getClass().equals(obj.getClass()))
return false;
Java是否正式记录了getClass()
方法的这种行为?
答案 0 :(得分:11)
是的,只要两个类由同一个类加载器加载,类对象就会一样。
但如果不是这样,那么这两个类必须被视为不同,即使它们可能共享相同的名称和代码。 (这在使用多个类加载器时很容易遇到,因此值得记住。)
答案 1 :(得分:3)
Java是否正式记录了getClass()方法的这种行为?
是的。我还没有(但)找到一个明确的陈述,但有很多地方暗示......或者更强大......由javadocs。例如:
Class.equals(Object)
没有javadoc,这意味着Object.equals(Object)
未被覆盖。
Object.getClass()
方法被指定为返回“此Object的运行时类”。 (注意它说“the”不是“a”。)javadoc还说“返回Class对象是被表示的类的静态同步方法锁定的对象”。如果任何类都有多个这样的对象,那么指定的同步机制将无法正常工作。
Class.forName(...)
方法被指定为返回“与具有给定字符串名称的类或接口关联的类对象”。 (再次注意,它说“不”是“a”。)
答案 2 :(得分:3)
这实际上取决于类加载器,因为我理解并不能保证:
http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44459
表现良好的类加载器维护这些属性:
- 给定相同的名称,一个好的类加载器应该总是返回相同的类对象。
- 如果类加载器L1将类C的加载委托给另一个加载器L2,那么对于作为直接超类或C的直接超接口出现的任何类型T,或作为C中的字段类型,或作为C中方法或构造函数的形式参数的类型,或者作为C,L1和L2中方法的返回类型应该返回相同的类对象。
恶意类加载器可能违反这些属性。但是,它不能破坏类型系统的安全性,因为Java虚拟机可以防范这种情况。
答案 3 :(得分:2)
至少有(至少)这个事实的隐含文件(引自the JavaDoc,强调我的):
返回: Class对象,表示此对象的运行时类。
答案 4 :(得分:1)
我知道它不是一个实例,而是设计。如果类由不同的类加载器加载,它们将不是同一个实例,因为对于JVM,类是不同的。
答案 5 :(得分:1)
如果两个类实例相同,则可以确定对象的类型相同。
Altough我发现没有具体的参考来回答你的问题,只是为了完整性Java语言规范书,section #4.3.4说:
4.3.4引用类型相同时
两种参考类型是相同的 运行时类型if:
它们都是类或两种接口类型,由 相同的类加载器,并具有相同的 二进制名称(第13.1节),在这种情况下 他们有时被认为是一样的 运行时类或相同的运行时 接口
它们都是数组类型,它们的组件类型是相同的 运行时类型(§10)。
答案 6 :(得分:1)
这是一个工作示例,演示具有相同类名的类可能具有不同的Class
个实例。但是equals
表明类实例确实是不同的,即使这些类共享相同的名称并从同一资源加载。
准备:在默认包中创建一个简单的类:
public class SomeClass{}
将类文件(仅限!!)存储在类路径中不是的文件夹中(如/tmp
)。
然后执行此方法:
public static void test() {
try {
URL[] urls = new URL[]{ new File("/tmp").toURL() };
ClassLoader cl1 = URLClassLoader.newInstance(urls);
ClassLoader cl2 = URLClassLoader.newInstance(urls);
Class clazz1 = cl1.loadClass("SomeClass");
Class clazz2 = cl2.loadClass("SomeClass");
System.out.println("Same names? " + clazz1.getName().equals(clazz2.getName()));
System.out.println("clazz1 == clazz2: " + (clazz1 == clazz2));
System.out.println("clazz1.equals(clazz2): " + (clazz1.equals(clazz2)));
} catch(Exception e) {
e.printStackTrace();
}
}