Гарантирует ли Java, что объект класса, возвращаемый getClass (), всегда будет одним и тем же экземпляром? [дубликат]
Возможный дубликат:
гарантирует ли Java этот объект.getClass() == объект.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()?
7 ответов:
Да, объект класса будет таким же, если два класса были загружены одним и тем же загрузчиком классов.
Но если это не так, то два класса должны рассматриваться как разные, даже если они могут иметь одно и то же имя и код. (Это то, с чем можно легко столкнуться при использовании нескольких загрузчиков классов, поэтому стоит помнить.)
Это действительно зависит от класса загрузчика и, как я понимаю, не гарантируется:
Http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44459
Корректные загрузчики классов сохраняют следующие свойства:
- при одном и том же имени хороший загрузчик классов должен всегда возвращать один и тот же объект класса.
- если загрузчик класса L1 делегирует загрузку класса C другому загрузчику L2, то для любого типа T, который имеет вид прямой суперкласс или прямой суперинтерфейс C, или как тип поля в C, или как тип формального параметра метода или конструктора в C, или как возвращаемый тип метода в C, L1 и L2 должны возвращать один и тот же объект класса.
Вредоносный загрузчик классов может нарушить эти свойства. Однако это не могло подорвать безопасность системы типов, потому что виртуальная машина Java защищает от этого.
Официально ли Java документирует такое поведение метода getClass ()?
Да, это так. Я не нашел (пока) явного утверждения ,но есть много мест, где это подразумевается... или сильнее ... по документации. Например:
Не существует javadoc для
Class.equals(Object), что означает, чтоObject.equals(Object)не переопределяется.Метод
Object.getClass()определяется как возвращающий"класс времени выполнения этого объекта". (Обратите внимание, что там написано" the " не "ля".) Javadoc также говорит: "[t]возвращаемый объект класса-это объект, который заблокирован статическими синхронизированными методами представленного класса". Если для любого класса существует более одного такого объекта, то указанный механизм синхронизации просто не будет работать.Методы
Class.forName(...)определяются как возвращающие"объект класса , связанный с классом или интерфейсом с заданным строковым именем". (Заметьте еще раз, здесь написано "the", а не "a".)
Существует (по крайней мере) неявная документация этого факта (цитируется из JavaDoc, Курсив мой):
Возвращает: объект класса, представляющий класс среды выполнения этого объекта.
Я знаю один случай, в котором это не так, но по замыслу. Если классы были загружены разными загрузчиками классов, они не будут одним и тем же экземпляром, потому что для JVM классы разные.
Если оба экземпляра класса одинаковы, вы можете быть уверены, что объекты имеют один и тот же тип.
Хотя я не нашел никакой конкретной ссылки, чтобы ответить на ваш вопрос, просто для полноты книги спецификации языка Java, раздел #4.3.4 говорит:
4.3.4 если ссылочные типы одинаковы
Два ссылочных типа одинаковы тип времени выполнения if:
Они оба являются классами или обоими типами интерфейса, определяются тот же класс загрузчика, и есть то же самое двоичное имя (§13.1), в этом случае иногда говорят, что это одно и то же. время выполнения в классе или же во время выполнения взаимодействие.
Они оба являются типами массивов, и их типы компонентов одинаковы тип времени выполнения (§10).
Вот один рабочий пример, который демонстрирует, что классы с одинаковым именем класса могут иметь разные экземпляры
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(); } }
Comments