Napiszę klasę java, która ma wiele getterów ... chcę uzyskać wszystkie metody gettera i wywołać je kiedyś ... Wiem, że są metod takich jak getMethods() lub getMethod (String name, Class ... parametersTypes), ale chcę po prostu uzyskać getter ..., użyj regex? ktoś może mi powiedzieć? Dzięki!Java Reflection: Jak mogę uzyskać wszystkie metody getter klasy java i wywołać je
Odpowiedz
Nie używać wyrażenia regularnego, użyj Introspector
:
for(PropertyDescriptor propertyDescriptor :
Introspector.getBeanInfo(yourClass).getPropertyDescriptors()){
// propertyEditor.getReadMethod() exposes the getter
// btw, this may be null if you have a write-only property
System.out.println(propertyDescriptor.getReadMethod());
}
Zwykle nie chcesz właściwości z Object.class, więc chcesz użyć metody z dwoma parametrami:
Introspector.getBeanInfo(yourClass, stopClass)
// usually with Object.class as 2nd param
// the first class is inclusive, the second exclusive
BTW: istnieją ramy, które robią to za Ciebie i prezentują Ci widok wysokiego poziomu. Na przykład. commons/beanutils ma metodę
Map<String, String> properties = BeanUtils.describe(yourObject);
(docs here), która właśnie to robi: odnaleźć i wykonać wszystkie pobierające i zapisać wynik w mapie. Niestety, BeanUtils.describe()
konwertuje wszystkie wartości właściwości na ciągi przed powrotem. WTF. Dzięki @danw
Aktualizacja:
Oto Java 8 metoda, która zwraca Map<String, Object>
na podstawie właściwości fasoli obiektu.
public static Map<String, Object> beanProperties(Object bean) {
try {
return Arrays.asList(
Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors()
)
.stream()
// filter out properties with setters only
.filter(pd -> Objects.nonNull(pd.getReadMethod()))
.collect(Collectors.toMap(
// bean property name
PropertyDescriptor::getName,
pd -> { // invoke method to get value
try {
return pd.getReadMethod().invoke(bean);
} catch (Exception e) {
// replace this with better error handling
return null;
}
}));
} catch (IntrospectionException e) {
// and this, too
return Collections.emptyMap();
}
}
Prawdopodobnie jednak chcesz poprawić obsługę błędów. Przykro nam z powodu obowiązującej normy, sprawdzone wyjątki uniemożliwiają nam pełną funkcjonalność.
Okazało się, że Collectors.toMap() nienawidzi wartości null. Oto bardziej niezbędna wersja powyższego kodu:
public static Map<String, Object> beanProperties(Object bean) {
try {
Map<String, Object> map = new HashMap<>();
Arrays.asList(Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors())
.stream()
// filter out properties with setters only
.filter(pd -> Objects.nonNull(pd.getReadMethod()))
.forEach(pd -> { // invoke method to get value
try {
Object value = pd.getReadMethod().invoke(bean);
if (value != null) {
map.put(pd.getName(), value);
}
} catch (Exception e) {
// add proper error handling here
}
});
return map;
} catch (IntrospectionException e) {
// and here, too
return Collections.emptyMap();
}
}
oto ta sama funkcjonalność w bardziej zwięzły sposób, używając JavaSlang:
public static Map<String, Object> javaSlangBeanProperties(Object bean) {
try {
return Stream.of(Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors())
.filter(pd -> pd.getReadMethod() != null)
.toJavaMap(pd -> {
try {
return new Tuple2<>(
pd.getName(),
pd.getReadMethod().invoke(bean));
} catch (Exception e) {
throw new IllegalStateException();
}
});
} catch (IntrospectionException e) {
throw new IllegalStateException();
}
}
A oto wersja Guava:
public static Map<String, Object> guavaBeanProperties(Object bean) {
Object NULL = new Object();
try {
return Maps.transformValues(
Arrays.stream(
Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors())
.filter(pd -> Objects.nonNull(pd.getReadMethod()))
.collect(ImmutableMap::<String, Object>builder,
(builder, pd) -> {
try {
Object result = pd.getReadMethod()
.invoke(bean);
builder.put(pd.getName(),
firstNonNull(result, NULL));
} catch (Exception e) {
throw propagate(e);
}
},
(left, right) -> left.putAll(right.build()))
.build(), v -> v == NULL ? null : v);
} catch (IntrospectionException e) {
throw propagate(e);
}
}
// Get the Class object associated with this class.
MyClass myClass= new MyClass();
Class objClass= myClass.getClass();
// Get the public methods associated with this class.
Method[] methods = objClass.getMethods();
for (Method method:methods)
{
System.out.println("Public method found: " + method.toString());
}
Tak, ale będziesz musiał również sprawdzić dla każdej metody, czy jest ona publiczna, niestatyczna, zwraca nieważne, nie oczekuje żadnego parametru i przestrzega konwencji get/isXyz. Introspector robi to za Ciebie, a także buforuje dane BeanInfo wewnętrznie dla innych aplikacji. –
nie zwraca pustki, czyli –
Można użyć ramy Reflections dla tego
import org.reflections.ReflectionUtils.*;
Set<Method> getters = ReflectionUtils.getAllMethods(someClass,
ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get"));
Nie wszystkie pobierające rozpoczynają się od "get": (1) gettery zwracające wartość boolean mogą zaczynać się od "is"; (2) klasa BeanInfo może określać, że dodatkowe metody to gettery.Naprawdę powinieneś dodać ograniczenie takie jak _ jeśli wiesz, że wszystkie twoje działania zaczynają się od "get", możesz to zrobić_. – toolforger
Należy zachować ogólny getter w każdym fasoli, tak aby wywołać getAttribute1() powinna być w stanie wywołać rodzajowe getter get („atrybut1”)
Ta ogólna getter wywoła w zakręcie prawidłowa getter
Object get(String attribute)
{
if("Attribute1".equals(attribute)
{
return getAttribute1();
}
}
Takie podejście wiąże się do utrzymania tej oddzielną listę w każdym bean, ale ten sposób uniknąć refleksji, która ma problemy z wydajnością, więc jeśli piszesz kod produkcyjny, który musi mieć dobre wyniki można wykorzystać powyższe wzór dla wszystkich twoich ziaren.
Jeśli jest to jakiś kod testowy lub kod użytkowy, który nie ma wysokich wymagań dotyczących wydajności, lepiej jest przyjąć inne podejście, ponieważ takie podejście jest podatne na błędy, chyba że można napisać pewien rodzaj kontrolera czasu kompilacji, który zapewnia tę ogólną funkcję pobierającą działa dla wszystkich atrybutów.
Spring oferuje łatwy BeanUtil method dla Bean introspekcji:
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, property);
Method getter = pd.getReadMethod();
Ten kod jest testowany OK.
private void callAllGetterMethodsInTestModel(TestModel testModelObject) {
try {
Class testModelClass = Class.forName("com.encoders.eva.testreflectionapi.TestModel");
Method[] methods = testModelClass.getDeclaredMethods();
ArrayList<String> getterResults = new ArrayList<>();
for (Method method :
methods) {
if (method.getName().startsWith("get")){
getterResults.add((String) method.invoke(testModelObject));
}
}
Log.d("sayanReflextion", "==>: "+getterResults.toString());
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
- 1. Java reflection question
- 2. Java Reflection getConstructor method
- 3. Jak wywołać metodę python z klasy java?
- 4. Jak wywołać metodę klasy abstrakcyjnej w java
- 5. Java Reflection - Uzyskaj listę pakietów
- 6. Java Reflection - Uzyskaj pola z klasy Sub oraz Super Class
- 7. Jak wywołać metodę prywatną spoza klasy java
- 8. java wywołanie metody z innej klasy
- 9. Pakiety i klasy Java
- 10. php: czy mogę utworzyć i wywołać funkcję wewnątrz metody klasy?
- 11. Jak mogę uzyskać wszystkie elementy panelu w Java Swing?
- 12. Java: wywołać metody wywołania w tablicy i wykonać później?
- 13. Jak wywołać niestandardowego operatora z Reflection
- 14. Jak wywołać metody Java na obiekcie z szablonu FreeMarker?
- 15. jak wywołać metodę klasy java w javascript używając ajax?
- 16. Czy mogę tanio wywołać metodę Java, aby uzyskać nazwę bieżącej metody?
- 17. Java - parametr Zastosowanie metody klasy w parametrze
- 18. Jak mogę uzyskać nazwę metody z nazwą i nazwą klasy?
- 19. Java Reflection getDeclaredMethod() z typami klas
- 20. Jak mogę uzyskać wszystkie odziedziczone klasy klasy bazowej?
- 21. AWS Lambda: Jak wywołać funkcję lambda z prostej klasy java
- 22. Java: Ogólne metody i numery
- 23. Java 8 uzyskać wszystkie elementy na liście
- 24. Java: Jak wywołać metodę klasy super-od wewnętrznej
- 25. Generics Java: jak uzyskać ogólny typ z metody?
- 26. języków statycznych i Reflection
- 27. Jak przyrządzić metody java?
- 28. Java - Czy można rozszerzyć wszystkie podklasy klasy o jedną klasę?
- 29. Programowanie z rdzeniem JAVA - Reflection API
- 30. Jak mogę wywołać metody Kotlin z reifikowanymi generycznymi z Javy?
Wow. Nie wiedziałem, że możesz to zrobić! Chłodny! –
Dzięki ..i przetestuj kod ... koniec wyniku to ** publiczny końcowy natywny java.lang.Class java.lang.Object.getClass() ** ... nie chcę go wywoływać. . Jak go usunąć? – user996505
@ user996505 Użyj Introspector.getBeanInfo (yourClass, Object.class), aby wyszukać wszystkie klasy poniżej Obiekt –