java.lang.reflect.Field class
A Field osztály információkat és dinamikus hozzáférést biztosít egy osztály vagy interfész egyetlen mezőjéhez. A mező lehetővé teszi a kiterjesztő típusú konverziót a get vagy set access művelet során, de IllegalArgumentException kivételt dob , ha szűkítés történne.
A Field objektum megszerzéséhez először írunk egy osztályt:
public class Person {
private String name;
private int age;
public boolean isMale;
protected String address;
public static final int MAX_AGE = 120;
public static final int MIN_AGE = 0;
}
És itt van a kódunk az osztállyal való munkához:
public class Main {
public static void main(String[] args) {
Field[] fields = Person.class.getDeclaredFields();
List<Field> actualFields = getFieldNames(fields);
System.out.println(actualFields);
}
static List<Field> getFieldNames(Field[] fields) {
return List.of(fields);
}
}
Így kapjuk meg osztályunk mezőinek listáját, amivel később dolgozunk. Íme az eredmény:
Most nézzük meg, mit tehetünk ezekkel az adatokkal. Beszéljünk a Field osztály metódusairól:
Módszer | Leírás |
---|---|
getType() | Egy osztály objektumot ad vissza, amely azonosítja az általa képviselt mező deklarált típusátTerülettárgy. |
getAnnotatedType() | Visszaadja anAnnotatedTypeobjektum, amely egy típus használatát reprezentálja a mező által képviselt mező deklarált típusának megadásához. |
getGenericType() | Visszatér atípusobjektum, amely az általa képviselt mező deklarált típusát képviseliTerülettárgy. |
getName() | Az általa képviselt mező nevét adja visszaTerülettárgy. |
getModifiers() | Az általa képviselt mező Java nyelvi módosítóit kódoló int-et ad visszaTerülettárgy. |
getAnnotations() | A mező megjegyzéseit adja vissza. Ha nincsenek megjegyzések, akkor üres tömböt ad vissza. |
getType(), getName() és getModifiers() metódusok
Használhatjuk a getType() metódust, hogy megkapjuk a mezőnk típusát. Írjunk egy módszert:
static void printTypes(List<Field> fields){
fields.forEach(e -> System.out.println(e.getType()));
}
És ezt az eredményt kapjuk:
int
logikai
osztály java.lang.String
int
int
Most adjunk hozzá egy metódust az osztályunkhoz, hogy megkapjuk egy mező nevét. Így könnyebben eligazodhatunk osztályunk mezői között.
static void printTypesAndNames(List<Field> fields){
fields.forEach(e -> System.out.printf("Field type - %s\nField name - %s\n\n", e.getType(), e.getName()));
}
Most már érthetőbb az eredmény:
Mezőnév - név
Mezőtípus - int
Mezőnév - életkor
Mezőtípus - logikai
érték Mezőnév - isMale
Mezőtípus - osztály java.lang.String
Mezőnév - cím
Mezőtípus - int
Mezőnév - MAX_AGE
Mezőtípus - int
Mezőnév - MIN_AGE
Nagy! Módosítsunk még egy kicsit a módszerünkön! Itt hozzáférésmódosítókat adunk hozzá
static void printFieldInfo(List<Field> fields){
fields.forEach(e -> System.out.printf("Field type - %s\nField name - %s\nModifiers - %s\n\n", e.getType(), e.getName(), Modifier.toString(e.getModifiers())));
}
És nézzük, mit ad vissza az e.getModifiers() ? Ez a metódus egy int értéket ad vissza , amely lehetővé teszi, hogy meghatározzuk a mezőnk hozzáférés-módosítóinak állapotát. A Modifier osztály a mező minden egyes módosítójáért felelős statikus változókat tartalmaz.
Tekerjük vissza a visszatérési értékünket a Modifier.toString() -be , és azonnal megkapjuk az értékét szövegként:
Mezőnév - név
Módosítók - privát
Mezőtípus - int
Mezőnév - életkor
Módosítók - privát
Mezőtípus - logikai érték
Mezőnév - isMale
Módosítók - public
Mezőtípus - osztály java.lang.String
Mezőnév - cím
Módosítók - védett
Mezőtípus - int
Mezőnév - MAX_AGE
Módosítók - publikus statikus végleges
Mezőtípus - int
Mezőnév - MIN_AGE
Módosítók - publikus statikus végleges
Így néz ki a Modifier.toString() nélkül :
Mezőnév - név
Módosítók - 2
Mezőtípus - int
Mezőnév - életkor
Módosítók - 2
Mezőtípus - logikai érték
Mezőnév - isMale
Módosítók - 1
Mezőtípus - osztály java.lang.String
Mezőnév - cím
Módosítók - 4
Mezőtípus - int
Mezőnév - MAX_AGE
Módosítók - 25
Mezőtípus - int
Mezőnév - MIN_AGE
Módosítók - 25
getAnnotations(), getAnnotatedType() és getGenericType() metódusok
Módosítsuk a Person osztályt úgy, hogy ezekkel a metódusokkal működjön. Megírjuk a saját megjegyzésünket, és alkalmazzuk a mezőinkre. És hozzáadunk még néhány mezőt.
Hozzunk létre két megjegyzést. A Pig latin változónevet átadjuk az egyiknek, a másodikat pedig az elemekhez:
@Target(value=ElementType.FIELD)
@Retention(value= RetentionPolicy.RUNTIME)
public @interface Name {
String name();
}
@Target({ ElementType.TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Number {
}
És megváltoztatjuk a fő osztályunkat és a Személy osztályt:
public class Person {
@Name(name = "Ame-nay")
private String name;
@Name(name = "User nicknames")
List<String> nicknames;
private final Class<Object> type;
private int @Number[] number;
public Person(Class<Object> type) {
this.type = type;
}
}
public static void main(String[] args) {
Field[] fields = Person.class.getDeclaredFields();
List<Field> actualFields = getFieldNames(fields);
printAdditionalInfo(actualFields);
}
static void printAdditionalInfo(List<Field> fields) {
System.out.println("\ngetAnnotatedType:");
fields.forEach(e -> System.out.println(e.getAnnotatedType()));
System.out.println("\ngetGenericType:");
fields.forEach(e -> System.out.println(e.getGenericType()));
System.out.println("\ngetAnnotations:");
fields.forEach(e -> System.out.println(Arrays.toString(e.getAnnotations())));
}
Itt az ideje, hogy megnézzük módszereink eredményeit, és kitaláljuk, mire valók:
java.lang.Class<java.lang.Object>
java.util.List<java.lang.String>
java.lang.String
int @Number()[]
getGenericType:
java.lang.Class<java.lang. Object>
java.util.List<java.lang.String>
class java.lang.String
osztály [Annotations-t
kapok:
[]
[@Name(name="\u0055\u0073\u0065\u0072\u0020\u006e\u0069\u0063" \u006b\u006e\u0061\u006d\u0065\u0073")]
[@Name(name="\u0041\u006d\u0065\u002d\u006e\u0061\u0079")] [
]
-
A getAnnotatedType visszaadja az adott mező megjegyzését, ha van ilyen. Megkapjuk a mezőre vonatkozó annotációt, és tökéletesen látjuk.
-
A getGenericType lehetővé teszi a paraméterezett típus helyes megjelenítését.
-
A getAnnotations visszaadja az objektumunkra alkalmazott megjegyzéseket.
Így könnyen hozzájuthatunk osztályunk egyes mezőinek minden adatához, illetve hozzáférési módosítóihoz, annotációihoz, adattípusaihoz.
java.lang.reflect.Method class
Szuper! Beszélgettünk az osztályunk területeiről. Itt az ideje, hogy beszéljünk a módszerekről.
Egy Method objektum megszerzéséhez a getMethod metódust hívjuk meg , és adjuk át a metódusunk nevét. Ez az alapvető módja a Method objektum beszerzésének :
Method getNameMethod = Person.class.getMethod("getName");
Folytatjuk a munkát az osztályunkkal. Adjunk hozzá gettereket és settereket, valamint hashCode, equals és toString metódusokat:
public class Person {
private String name;
private int age;
public boolean isMale;
protected String address;
public static final int MAX_AGE = 120;
public static final int MIN_AGE = 0;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isMale() {
return isMale;
}
public void setMale(boolean male) {
isMale = male;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", isMale=" + isMale +
", address='" + address + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && isMale == person.isMale && Objects.equals(name, person.name) && Objects.equals(address, person.address);
}
@Override
public int hashCode() {
return Objects.hash(name, age, isMale, address);
}
}
Most készítsünk elő egy metóduskészletet, amelyet a Method osztály segítségével fogunk megvizsgálni. Íme a legfontosabb módszerek listája:
Módszer | Leírás |
---|---|
getName() | A metódus nevét adja vissza. |
getModifiers() | A metódus hozzáférésmódosítóját adja vissza. |
getReturnType() | A metódus visszatérési típusát adja vissza. |
getGenericReturnType() | A metódus visszatérési típusát adja vissza, figyelembe véve az általános metódusokat. |
getParameterTypes() | Metódusparaméterek tömbjét adja vissza. |
getGenericParameterTypes() | Metódusparaméterek tömbjét adja vissza, figyelembe véve az általános módszereket. |
getExceptionTypes() | Visszaadja azokat a kivételeket, amelyeket a metódus dobhat. |
getGenericExceptionTypes() | Visszaadja azokat a kivételeket, amelyeket a metódus dobhat, figyelembe véve a paraméterezett típusokat. |
getAnnotations() | A metódus megjegyzéseit adja vissza, beleértve a szülő megjegyzéseket. |
getDeclaredAnnotations() | A metódus megjegyzéseit adja vissza, kivéve a szülő megjegyzéseket. |
Ahhoz, hogy megkapjuk az osztályakarat metódusainak tömbjét, hívhatjuk ezt a metódust:
Method[] methods = Person.class.getDeclaredMethods();
Ez megadja nekünk az összes módszert az osztályunkban.
getName() és getModifiers() metódusok
A getName segítségével megkaphatjuk az egyes metódusok nevét:
static List<String> getMethodsName(Method[] methods) {
return Arrays.asList(methods)
.stream()
.map(Method::getName)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}
Most, hogy megkapjuk a módosítókat, írjunk egy módszert, amely a getModifiers-t használja :
static List<String> getModifiers(Method[] methods) {
return Arrays
.stream(methods)
.map(Method::getModifiers)
.map(String::valueOf)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}
Íme a fő módszerünk:
public static void main(String[] args) {
Method[] methods = Person.class.getDeclaredMethods();
System.out.println(getMethodsName(methods));
System.out.println(getModifiers(methods));
}
Eredményünk:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Minden metódusunk rendelkezik nyilvános módosítóval, így az utolsó metódus egy tömböt ad vissza. Ha módosítjuk a kódunkat, magukat a módosítóinkat fogjuk látni:
public static void main(String[] args) {
Method[] methods = Person.class.getDeclaredMethods();
System.out.println(getMethodsName(methods));
System.out.println(modifyModifiers(getModifiers(methods)));
}
nyilvános, nyilvános, nyilvános]
getReturnedType()
Ezzel a metódussal megkaphatjuk a metódus visszatérési típusát:
static void getReturnedType(Method[] methods) {
Arrays.stream(methods)
.map(Method::getReturnType)
.forEach(System.out::println);
}
logikai
osztály java.lang.String
int
void
osztály java.lang.String
logikai
int
void
void
void
getGenericReturnType()
Adjunk a Person osztályunknak egy metódust, amely paraméterezett típusba csomagolva adja vissza a típust, és próbáljuk meg visszaadni a visszatérési értékét:
public List<String> someMethod() {
// Very useful and important method
return null;
}
És frissítjük fő módszerünket:
static void getGenericReturnType(Method[] methods) {
Arrays.stream(methods)
.map(Method::getGenericReturnType)
.forEach(System.out::println);
}
Módszerünk eredménye:
logikai
osztály java.lang.String
int
void
osztály java.lang.String
logikai
int
void
void
void
java.util.List<java.lang.String>
getParameterTypes() és getGenericParameterTypes() metódusok
Folytatjuk a Személy osztály módosítását, két további metódus hozzáadásával:
public List<String> someMethod(List<String> list, String s) {
// Very useful and important method
return null;
}
Az első a módszereink paramétereit, a második pedig a paraméterezett típusokat is megadja.
static void getParameterTypes(Method[] methods) {
Class<?>[] types = method.getParameterTypes();
for (Class<?> type : types) {
System.out.println(type);
}
}
static void getGenericParameterTypes(Method[] methods) {
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
System.out.println(type);
}
}
Csak az egyik módszerünket fogjuk elérni. Egy metódus adott névvel való eléréséhez meghívjuk a getMethod-ot , és átadjuk a kívánt metódus nevét és paramétereit:
public static void main(String[] args) throws NoSuchMethodException {
Method currentMethod = Person.class.getMethod("someMethod", List.class, String.class);
getParameterTypes(currentMethod);
System.out.println();
getGenericParameterTypes(currentMethod);
}
A kódunk futtatásával látni fogjuk, hogy a metódusok miben térnek el egymástól, és mit adnak vissza:
class java.lang.String
java.util.List<java.lang.String>
osztály java.lang.String
getExceptionTypes() és getGenericExceptionTypes() metódusok
Ezekkel a metódusokkal olyan kivételek tömbjét kaphatjuk meg, amelyeket metódusunk dobhat, valamint paraméterezett típusú kivételeket (ha vannak ilyenek). Használjunk egy új példát, amelynek rejtett statikus osztálya van:
private static class Processor {
private void init() {}
private void process() throws IOException {}
}
És meghívjuk a metódusokat a Processor osztályunkban:
public static void main(String... args) throws NoSuchMethodException {
Method method = Processor.class.getDeclaredMethod("process");
Type[] type = method.getExceptionTypes();
System.out.println(Arrays.toString(type));
}
Most láthatjuk a kivételünket:
Most paraméterezzük a típust. Módosítjuk fő osztályunkat:
private static class Processor<E extends IOException> {
private void process() throws E {
}
}
És a fő módszer kódja:
public static void main(String... args) throws NoSuchMethodException {
Method m = Processor.class.getDeclaredMethod("process");
Type[] t = m.getGenericExceptionTypes();
System.out.println(Arrays.toString(t));
for (Type type : t) {
if (type instanceof TypeVariable) {
for (Type type1 : ((TypeVariable) type).getBounds()) {
System.out.println(type1);
}
}
}
}
Ezen a metóduson belül kaptunk egy TypeVariables objektumot, amely a típusváltozók általános szülőfelülete. Ezen belül pedig megkaphatjuk a belső paramétert, nevezetesen a beágyazott kivételünket:
osztály java.io.IOException
getAnnotations() és getDeclaredAnnotations() metódusok
Folytassuk az új osztály használatát, és adjunk hozzá néhány megjegyzést. Létrehozzuk saját kommentárunkat :
@Retention(RetentionPolicy.RUNTIME)
@interface Annotation {
public String key();
public String value();
}
És alkalmazzuk a módszerünkre:
@Annotation(key = "key", value = "value")
private void process() throws E{
}
És természetesen hozzáadunk egy módszert az összes megjegyzésünk megjelenítéséhez:
static void getMethodAnnotations(Class<?> clazz) {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
System.out.println(Arrays.toString(method.getAnnotations()));
System.out.println();
}
}
Fő módszerünk megvalósítása :
public static void main(String... args) {
Class clazz = Processor.class;
getMethodAnnotations(clazz);
}
A kapott képernyőkimenet a következő:
[@com.company.Main&Annotation(key="key", value="value")]
Így kaphatjuk meg a metódusainkra alkalmazott annotációkat, a getAnnotations metódus pedig lehetővé teszi az osztály szülőannotációinak elérését is.
A mai napon megismerkedtünk azzal, hogyan működhet a reflexió módszerekkel, mezőkkel, és milyen adatokat nyerhetünk vele!
GO TO FULL VERSION