Посмотрите, существует ли поле в классе

У меня есть класс с различными переменными

public class myClass{

    public int id;
    public String category;
    public String description;
    public String start;
    public String end;
}

Есть ли способ проверить, создавая внутреннюю функцию или проверяя из вызывающего объекта, существует ли переменная или нет?

например. Чтобы проверить, содержит ли myClass переменную, называемую "категория" (она делает). Или он содержит категорию под названием "foo" (это не так).

Ответы

Ответ 1

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

Object someObject = ...
Class<?> someClass = someObject.getClass();
Field someField = someClass.getField("foo");

Метод getField() выдаст исключение, если поле не может быть найдено.

Ответ 2

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

Вместо этого рассмотрим следующую альтернативу:

public boolean doesObjectContainField(Object object, String fieldName) {
    Class<?> objectClass = object.getClass();
    for (Field field : objectClass.getFields()) {
        if (field.getName().equals(fieldName)) {
            return true;
        }
    }
    return false;
}

Или более сжатая форма с использованием потоков Java 8:

public boolean doesObjectContainField(Object object, String fieldName) {
    return Arrays.stream(object.getClass().getFields())
            .anyMatch(f -> f.getName().equals(fieldName));
}

Эти фрагменты кода не полагаются на исключения как поток управления и на самом деле вообще не требуют обработки исключений, что сделает вашу реализацию более простой и удобочитаемой. Вы просто назовете один из вышеперечисленных методов с фрагментом кода, подобным следующему:

Object someObject = ... ;
boolean fieldExists = doesObjectContainField(someObject, "foo");

В качестве побочного примечания, если вам нужно было получить доступ к закрытым полям класса (но не к родительским классам), вы могли бы просто заменить вызов на getFields на getDeclaredFields.

Ответ 3

Как уже упоминалось, отражение - это то, что вам нужно.

Если вам нужно получить доступ к частному полю, вы можете использовать Class.getDeclaredField(String name)

Ответ 4

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

Например:

Class<?> clz = MyClass.class;
try {
    Field f = clz.getField("foo")
}
catch ( NoSuchFieldException ex) {
    // field doesn't exist
}
catch (SecurityException ex) {
    // no access to field
}

Ответ 6

Используйте следующие методы, которые используют Reflections -

  private Set<String> getAllFields(final Class<?> type) {
        Set<String> fields = new HashSet<String>();
        for (Field field : type.getDeclaredFields()) {
            fields.add(field.getName());
        }

        if (type.getSuperclass() != null) {
            fields.addAll(getAllFields(type.getSuperclass()));
        }
        return fields;
    }       
    private boolean listHasProperty(final Set<String> properties, final String propertyName) {
        if (properties.contains(propertyName)) {
            return true;
        }
        return false;
    }

Затем проверьте, присутствует ли свойство с помощью -

Set<String> fieldSet = getAllFields(object.getClass());
boolean isPresent=listHasProperty(fieldSet , sourceProperty)

Подробнее см. post

Ответ 7

Это немного неудобно делать за один шаг.

Когда мы перешли к концепции полиморфизма, есть проблемы, такие как генерация недостающих объектов для класса (класс ABC), который динамически принимает данные, ссылаясь на другие выделенные классы (класс ABCXMLDOMnodes, класс ABCHTMLDOMnodes), который содержит те же поля, но статический и конечный. Надеюсь, вы получили это требование.

1.Creating ArrayList полей Простые имена этих трех классов как глобальные.

 private static ArrayList<String> getAllFieldsSimpleNames(Class<?> beanClass) {
    ArrayList<String> fieldNames = new ArrayList<String>();
    Field[] fields = beanClass.getDeclaredFields();
    for (Field field : fields) {
        fieldNames.add(field.getName());
    }
    return fieldNames;
}

2. И тогда каждый раз, когда мы генерируем объект, мы проверяем поля (скажем, > 10 полей) на классы-помощники, такие как ниже, я легко чувствую.

 for(String a :abcFieldNames){
        if(abcXMLfieldnames.contains(a)){
        //code here
        }else if(abcHTMLfieldnames.contains(a){
        //code here
        }
    }

Другим простейшим и динамичным способом является создание

      HashMap<Class<?>, ArrayList<String>> = ...
    hm.put(ABC.class, getAllFieldsSimpleNames(ABC.class));
    hm.put(ABCXMLDOMnodes.class, getAllFieldsSimpleNames(ABCXMLDOMnodes.class));
if(hm.get(ABCXMLDOMnodes.class).contains("a"){...}

Мое предложение для сети Oracle Corp. JAVA заключается в том, что "класс класса" может предоставить метод, который возвращает список имен полей данного класса как тип строки, будет полезен.