Я пытаюсь использовать Clojure's (bean obj)
для извлечения неизменяемой карты, связанной с объектом.Проверка экземпляров непубличных классов с использованием java.bean API
В стандартной библиотеке Clojure 1.4.0, это реализовано примерно как так (перевод в псевдокоде предназначен доступным для людей, незнакомых с Clojure):
import java.beans.PropertyDescriptor;
import java.beans.Introspector;
function introspect(Object obj) {
Class clazz = obj.getClass();
PropertyDescriptor descriptors[] =
Introspector
.getBeanInfo(clazz)
.getPropertyDescriptors();
Map retval = new HashMap();
for(pd in descriptors) {
name = pd.getName();
method = pd.getReadMethod();
if(method.getParameterTypes().length != 0)
continue;
retval.set(name, method.invoke(obj, nil));
}
/* the real implementation does more magic below here,
but the above is sufficient for this question */
return retval;
}
По большей части, это работает отлично - java.bean.Introspector не возвращает непубличные методы в своей реализации по умолчанию BeanInfo. Однако, когда проверяемый объект является экземпляром непубличного класса, он возвращает общедоступные методы в этом классе, даже если они не могут быть вызваны, не поднимая IllegalArgumentException
(«Нельзя вызвать общедоступный метод не- публичный класс ").
Как это можно исправить? Я просматриваю документацию для java.lang.Class, и я не вижу очевидного способа определить разрешения класса, которые не связаны с блоком try/catch для java.lang.SecurityException ... что не совсем похоже на меня лучшая практика. Более того, в случае, когда метод в непубличном классе реализует открытый интерфейс, должен быть доступен какой-то механизм, чтобы определить, что этот метод можно безопасно назвать.
К сожалению, в случае, когда частный класс реализует открытый интерфейс, этот ответ сам по себе не является достаточным для определения того, что методы, определенные через этот интерфейс, доступны. В сочетании с возможностью идентификации интерфейса из PropertyDescriptor этого, вероятно, будет достаточно. –
Если объект относится к классу, который реализует интерфейс (который является общедоступным по определению), вы должны иметь возможность вызывать методы на интерфейсе независимо от конфиденциальности класса. Все остальное - ошибка. Обратите внимание, что Java имеет много ненужного багажа, вызванного тем, как внутренние языки были добавлены к языку. Частные классы имеют смысл только как внутренние классы. В структуре вашего примера может быть что-то, что мне не хватает. – sw1nn
У меня есть непубличный класс с рядом общедоступных методов. Некоторые из этих методов можно назвать публично в силу интерфейсов, реализующих класс; некоторые из этих публичных методов не могут быть вызваны, поскольку они не определяются каким-либо открытым классом или интерфейсом, но только внутри самого негосударственного класса. Реальный случай использования вождения это «com.atlassian.crowd.embedded.ofbiz.OfBizUser', из продукта Atlasian's Crowd, используемого в Jira; Я согласен с тем, что для них нет смысла публиковать метод в непубличном классе, но мой единственный контроль над этим - это подача билета, предлагающего столько же. –