Как проверить, имеет ли данный класс поле и он был инициализирован?

Как проверить, имеет ли данный класс определенное поле и если он инициализирован (имеет значение в данный момент)?

abstract class Player extends GameCahracter {

}

public class Monster extends GameCahracter{

    public int level = 1;
}
abstract class GameCharacter{

   public void attack(GameCahracter opponent){

         if (opponent instanceof Monster && ){ // << here I have to know is it instance of Monster and if it has initialized value
           }
}

Ответ 1

//Load the class 

Class clazz = Class.forName("your.class.ClassName");
Field field = clazz.getField("fieldName")
if(field!=null){
 //field exist now check if its initialized or not, or if its primitive field check against its assumed initialized value
 if(ClassName.fieldName!=null){
    //yes initilized
 }
}

Ответ 2

Вы можете использовать отражение, например, следующим образом:

Class.forName("Foo").getFields() 

И затем вы можете снова проверить, если конкретный объект имеет это поле, инициализированное с помощью отражения.

Ответ 3

Вам не нужно использовать отражение для этого, вы можете просто сделать это с условием if.

 if (opponent !=null && opponent instanceof Monster && ((Monster) opponent).level==1){ // << here I have to know is it instance of Monster and if it has initialized value
           }

Вы можете проверить, что экземпляр не является нулевым, если экземпляр не null и его экземпляр Monster, то в вашем случае его определенно инициализирован. Переменные экземпляра, инициализированные значениями по умолчанию, когда создается новый экземпляр, если экземпляр противника монстра, то уровень имеет значение 1.

Ответ 4

Чтобы узнать, обладает ли класс свойством без использования исключения, вы можете использовать следующие методы:

private Boolean objectHasProperty(Object obj, String propertyName){
    List<Field> properties = getAllFields(obj);
    for(Field field : properties){
        if(field.getName().equalsIgnoreCase(propertyName)){
            return true;
        }
    }
    return false;
}

private static List<Field> getAllFields(Object obj){
    List<Field> fields = new ArrayList<Field>();
    getAllFieldsRecursive(fields, obj.getClass());
    return fields;
}

private static List<Field> getAllFieldsRecursive(List<Field> fields, Class<?> type) {
    for (Field field: type.getDeclaredFields()) {
        fields.add(field);
    }

    if (type.getSuperclass() != null) {
        fields = getAllFieldsRecursive(fields, type.getSuperclass());
    }

    return fields;
}

И просто позвоните:

objectHasProperty(objInstance, "myPropertyName");

На самом деле не имеет значения экземпляр класса, чтобы увидеть, обладает ли класс свойством, но я сделал это, просто чтобы быть немного более дружелюбным. Просто для завершения: я сделал getAllFields рекурсивным, чтобы получить все методы суперклассов (в моем случае это важно)

После этого, если вы хотите увидеть, каково значение свойства в нужном объекте, вы можете просто вызвать:

PropertyUtils.getProperty(objInstance, "myPropertyName");

Помните: если objInstance не имеет этого свойства, вызов выше будет бросать NoSuchMethodException (Вот почему вам нужно использовать первый код, чтобы узнать, обладает ли класс свойством)