Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > переменная class


Автор: Pawl 14.10.2011, 18:22
Уважаемые форумчане, такой вопрос,
Озаботился назначением переменной class: зачем нужна, какого она типа, где находится (в классе Object ее нет, в других - тоже не видел) и вообще, что она делает?
Очень был бы рад простому и доходчивому разъяснению этого вопроса.
Спасибо!

Автор: LSD 14.10.2011, 18:48
Нет такой переменной. Запись:
Код

SomeClass.class

это просто указание компилятору, что надо взять Class объект описывающий класс SomeClass. Никакой переменной нет.

P.S. Попробуй
Код

int.class

Автор: Samotnik 14.10.2011, 22:14
быть может речь о http://en.wikipedia.org/wiki/Classpath_%28Java%29  ?

Автор: Pawl 15.10.2011, 08:33
Цитата(LSD @  14.10.2011,  18:48 Найти цитируемый пост)
это просто указание компилятору, что надо взять Class объект описывающий класс SomeClass. Никакой переменной нет.

т. е. это что-то вроде Class.forName("SomeClass")? Да, я написал System.out.println(int.class); - получилось int. А если написать Class.forName("int"); - получается ошибка ClassNotFoundException. 

Автор: dorogoyIV 15.10.2011, 14:02
а документацию почитать по "Class", "Class.forName(...)" не судьба?

Автор: math64 15.10.2011, 20:16
Цитата(Pawl @  15.10.2011,  08:33 Найти цитируемый пост)
т. е. это что-то вроде Class.forName("SomeClass")?

Компилируется в байт-код именно так, но для классов, но не для int.
Поэтому если пропустить jar через обфускатор, который переименует SomeClass в a, код работать не будет.
Такой код выдержит прогон через обфускатор:
Код

final Class someClassClass = new SomeClass.getClass();
final Class someAbstractClassClass = new SomeAbstractClass[0].getClass().getComponentType();


Автор: Pawl 16.10.2011, 11:49
Цитата(math64 @  15.10.2011,  20:16 Найти цитируемый пост)
Компилируется в байт-код именно так

спасибо за информацию.
Хочу еще уточнить: при вызове метода Class.forName("SomeClass") (документацию по которому я, кстати, читал),  возвращается объект класса Class для класса SomeClass, и при этом происходит инициализация статической части SomeClass. Действительно, если я напишу
Код

class Abs {
    static {
        System.out.println("its worked!");
    }
}

public class Iniz {
    public static void main(String ...args) throws ClassNotFoundException {
        Class c = Class.forName("Abs");
        System.out.println(c);
    }        
}

то этот код при запуске выдаст 
Цитата

its worked!
class Abs

Но если сделать так
Код

class Abs {
    static {
        System.out.println("its worked!");
    }
}

public class Iniz {
    public static void main(String ...args) throws ClassNotFoundException {
        Class<Abs> c = Abs.class;
        System.out.println(c);
    }        
}

то в результате будет просто
Цитата

class Abs

Т. е. получается, что SomeClass.class - это не тоже самое, что Class.forName("SomeClass"). Значит ли это, что в первом случае просто создается объект класса Class для SomeClass, без инициализации статической части SomeClass?

Автор: math64 16.10.2011, 13:43
Объект не создаётся в любом случае, а только загружается байт-код класса.
Но в первом случае выполняются статичесткая инициализация.
То что SomeClass.class транслируется как Class.forName("SomeClass") я проверял в JDK, в котором не было шаблонных функций. В новых JDK видимо транслируется по-другому, заметь: у тебя Class<Abs> c = Abs.class; а не Class c = Abs.class;

Добавлено через 6 минут и 59 секунд
Вот как транслируется твой пример (javap -c Iniz):
Код

public static void main(java.lang.String[])   throws java.lang.ClassNotFoundException;
  Code:
   0:    ldc_w    #2; //class Abs
   3:    astore_1
   4:    getstatic    #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   7:    aload_1
   8:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   11:    return

Автор: math64 16.10.2011, 14:01
Вот пул констант:
Код

const #1 = Method    #6.#17;    //  java/lang/Object."<init>":()V
const #2 = class    #18;    //  Abs
const #3 = Field    #19.#20;    //  java/lang/System.out:Ljava/io/PrintStream;
const #4 = Method    #21.#22;    //  java/io/PrintStream.println:(Ljava/lang/Object;)V
const #5 = class    #23;    //  Iniz
const #6 = class    #24;    //  java/lang/Object
const #7 = Asciz    <init>;
const #8 = Asciz    ()V;
const #9 = Asciz    Code;
const #10 = Asciz    LineNumberTable;
const #11 = Asciz    main;
const #12 = Asciz    ([Ljava/lang/String;)V;
const #13 = Asciz    Exceptions;
const #14 = class    #25;    //  java/lang/ClassNotFoundException
const #15 = Asciz    SourceFile;
const #16 = Asciz    Iniz.java;
const #17 = NameAndType    #7:#8;//  "<init>":()V
const #18 = Asciz    Abs;
const #19 = class    #26;    //  java/lang/System
const #20 = NameAndType    #27:#28;//  out:Ljava/io/PrintStream;
const #21 = class    #29;    //  java/io/PrintStream
const #22 = NameAndType    #30:#31;//  println:(Ljava/lang/Object;)V
const #23 = Asciz    Iniz;
const #24 = Asciz    java/lang/Object;
const #25 = Asciz    java/lang/ClassNotFoundException;
const #26 = Asciz    java/lang/System;
const #27 = Asciz    out;
const #28 = Asciz    Ljava/io/PrintStream;;
const #29 = Asciz    java/io/PrintStream;
const #30 = Asciz    println;
const #31 = Asciz    (Ljava/lang/Object;)V;


Добавлено через 5 минут и 19 секунд
но класс всё-таки грузится: если удалить Abs.class получишь
Код

Exception in thread "main" java.lang.NoClassDefFoundError: Abs
    at Iniz.main(Iniz.java:9)

Автор: LSD 17.10.2011, 10:10
Цитата(Pawl @  15.10.2011,  09:33 Найти цитируемый пост)
А если написать Class.forName("int"); - получается ошибка ClassNotFoundException.

Класс для примитивного типа, так не загрузишь. Там есть специальный метод Class.getPrimitiveClass(), но он приватный для java.lang.

В Class.forName() можно указать, что не надо вызывать инициализацию класса. Эффект будет тот же самый.

Автор: Pawl 17.10.2011, 10:11
Спасибо, math64, но всё-же...smile
Цитата(math64 @  16.10.2011,  13:43 Найти цитируемый пост)
Объект не создаётся в любом случае

А как же тогда понимать описание метода forName в JDK-docs?
Цитата

Returns the Class object associated with the class or interface with the given string name

разве Returns the Class object не переводится, как "возвращает объект класса"?
Цитата(math64 @  16.10.2011,  13:43 Найти цитируемый пост)
тебя Class<Abs> c = Abs.class; а не Class c = Abs.class;

если написать Class c = Abs.class; результат останется прежним.
Цитата(math64 @  16.10.2011,  14:01 Найти цитируемый пост)
Exception in thread "main" java.lang.NoClassDefFoundError:

В JDK-docs про NoClassDefFoundError написано: 
Цитата

Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found. 

Интересно, что тут значит "definition of the class" (определение класса)?

Добавлено через 5 минут и 33 секунды
Цитата(LSD @  17.10.2011,  10:10 Найти цитируемый пост)
В Class.forName() можно указать, что не надо вызывать инициализацию класса. Эффект будет тот же самый.

согласен, написал Class c = Class.forName("Abs", false, null); получил ClassNotFoundException!

Автор: LSD 17.10.2011, 10:22
Цитата(Pawl @  17.10.2011,  11:11 Найти цитируемый пост)
согласен, написал Class c = Class.forName("Abs", false, null); получил ClassNotFoundException! 

Я говорил про случай, когда класс загружается, но не инициализируется, как в случае:
Код

Class<Abs> c = Abs.class;
System.out.println(c);

Автор: math64 17.10.2011, 13:23


Цитата(Pawl @  17.10.2011,  10:11 Найти цитируемый пост)

Цитата
Returns the Class object associated with the class or interface with the given string name

разве Returns the Class object не переводится, как "возвращает объект класса"?

Возвращает объект типа Class, ассоциированный с классом или интерфейсом с заданным строкой name именем.
Я имет ввиду, что не создаётся объект класса, заданого строкой name (объект абстрактного класса или интерфейса, понятно, не может быть создан в любом случае).
Кстати, объект типа Class создаётся только при первом вызове - в дальнейшем код эквивалентен загрузке константы (см. байт-код)
NoClassDefFoundError получишь если файл Abs.class удалён или попорчен - ClassLoader не сможет его загрузить или найти в нём определение класса.

Автор: Pawl 17.10.2011, 20:36
Всем Спасибо, теперь стало более понятно!
Цитата(LSD @  17.10.2011,  10:22 Найти цитируемый пост)
Я говорил про случай, когда класс загружается, но не инициализируется

Понял, когда я написал вот так
Код

Class c = Class.forName("Abs", false, Abs.class.getClassLoader());
System.out.println(c);

Получился такой же вывод, как в коде
Код

Class c = Abs.class;
System.out.println(c);


Автор: math64 18.10.2011, 08:02
Цитата(Pawl @  17.10.2011,  20:36 Найти цитируемый пост)
Понял, когда я написал вот так
Код

Class c = Class.forName("Abs", false, Abs.class.getClassLoader());
System.out.println(c);

Смысла в таком коде особого нет - ты два раза получаешь объект Class для класса Abs двуми способами - сначала через Abs.class, затем через Class.forName().
В случае, когда текущий класс и класс Abs имеют тот же загрузщик (в обычной ситуации это так), можно так:
Код

Class c = Class.forName("Abs", false, getClass().getClassLoader());
System.out.println(c);


Автор: Pawl 18.10.2011, 08:17
Цитата(math64 @  18.10.2011,  08:02 Найти цитируемый пост)
Class c = Class.forName("Abs", false, getClass().getClassLoader());

Спасибо! только предыдущие коды у меня работали сразу в методе main, поэтому я написал такую вот тавтологиюsmile для твоего примера пришлось сделать конструкторsmile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)