java.lang.reflect.Field sınıfı
Field sınıfı, bir sınıf veya arayüzün tek bir alanı hakkında bilgi ve bu alana dinamik erişim sağlar . Field ayrıca bir erişim alma veya ayarlama işlemi sırasında genişleyen bir tür dönüşümüne izin verir, ancak daralma meydana gelirse bir IllegalArgumentException atar.
Bir Field nesnesi elde etmek için önce bir sınıf yazacağız:
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;
}
Ve işte o sınıfla çalışmak için kodumuz:
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);
}
}
Daha sonra çalışacağımız sınıfımızın alanlarının listesini bu şekilde alıyoruz. İşte sonuç:
Şimdi bu verilerle neler yapabileceğimize bakalım. Field sınıfının metotlarından bahsedelim :
Yöntem | Tanım |
---|---|
getType() | Bununla temsil edilen alanın belirtilen türünü tanımlayan bir Class nesnesi döndürür.Alannesne. |
getAnnotatedType() | bir döndürürAçıklamalıTürBu Alan tarafından temsil edilen alanın belirtilen türünü belirtmek için bir türün kullanımını temsil eden nesne. |
getGenericType() | bir döndürürTipbununla temsil edilen alanın belirtilen türünü temsil eden nesneAlannesne. |
getName() | Bununla temsil edilen alanın adını döndürürAlannesne. |
getModifiers() | Bununla temsil edilen alan için Java dili değiştiricilerini kodlayan bir int döndürür.Alannesne. |
getAnnotations() | Bu alan için açıklamaları döndürür. Ek açıklama yoksa, boş bir dizi döndürür. |
getType(), getName() ve getModifiers() yöntemleri
Alanımızın türünü elde etmek için getType() yöntemini kullanabiliriz . Bir metod yazalım:
static void printTypes(List<Field> fields){
fields.forEach(e -> System.out.println(e.getType()));
}
Ve şu sonucu elde ederiz:
int
boole
sınıfı java.lang.String
int
int
Şimdi bir alanın adını almak için sınıfımıza bir metot ekleyelim. Bu, sınıfımızın alanlarında gezinmeyi kolaylaştıracaktır.
static void printTypesAndNames(List<Field> fields){
fields.forEach(e -> System.out.printf("Field type - %s\nField name - %s\n\n", e.getType(), e.getName()));
}
Şimdi sonuç daha anlaşılır:
Alan adı - ad
Alan türü - int
Alan adı - age
Alan türü - boolean
Alan adı - isMale
Alan türü - class java.lang.String
Alan adı - adres
Alan türü - int
Alan adı - MAX_AGE
Alan türü - int
Alan adı - MIN_AGE
Harika! Yöntemimizi biraz daha değiştirelim! Buraya erişim değiştiricileri ekleyeceğiz
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())));
}
Ve e.getModifiers()' ın ne döndürdüğüne bakalım . Bu yöntem , alanımızın erişim değiştiricilerinin durumunu belirlememizi sağlayan bir int döndürür . Değiştirici sınıfı , alanın her belirli değiştiricisinden sorumlu statik değişkenler içerir.
Dönüş değerimizi Modifier.toString() içine saralım ve değerini hemen metin olarak alalım:
Alan adı - ad
Değiştiriciler - özel
Alan türü - int
Alan adı - yaş
Değiştiriciler - özel
Alan türü - boolean
Alan adı - isMale
Değiştiriciler - public
Alan türü - sınıf java.lang.String
Alan adı - adres
Değiştiriciler - korumalı
Alan tipi - int
Alan adı - MAX_AGE
Değiştiriciler - public static final
Alan tipi - int
Alan adı - MIN_AGE
Değiştiriciler - public static final
İşte Modifier.toString() olmadan nasıl göründüğü :
Alan adı - ad
Değiştiriciler - 2
Alan türü - int
Alan adı - yaş
Değiştiriciler - 2
Alan türü - boolean
Alan adı - isMale
Değiştiriciler - 1
Alan türü - sınıf java.lang.String
Alan adı - adres
Değiştiriciler - 4
Alan tipi - int
Alan adı - MAX_AGE
Değiştiriciler - 25
Alan tipi - int
Alan adı - MIN_AGE
Değiştiriciler - 25
getAnnotations(), getAnnotatedType() ve getGenericType() yöntemleri
Bu yöntemlerle çalışmak için Person sınıfını değiştirelim . Kendi ek açıklamamızı yazıp alanlarımıza uygulayacağız. Ve birkaç alan daha ekleyeceğiz.
İki ek açıklama oluşturalım. Pig Latince'deki değişken ismini one'a aktaracağız ve ikincisini elementler için kullanacağız:
@Target(value=ElementType.FIELD)
@Retention(value= RetentionPolicy.RUNTIME)
public @interface Name {
String name();
}
@Target({ ElementType.TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Number {
}
Ve ana sınıfımızı ve Person sınıfını değiştireceğiz :
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())));
}
Yöntemlerimizin sonuçlarına bakmanın ve bunların ne işe yaradığını anlamanın zamanı geldi:
java.lang.Class<java.lang.Object>
java.util.List<java.lang.String>
java.lang.String
int @Number()[]
getGenericType:
java.lang.Class<java.lang. Nesne>
java.util.List<java.lang.String>
sınıfı java.lang.String
sınıfı [I
getAnnotations:
[]
[@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")] [
]
-
getAnnotatedType, varsa, verilen alan için açıklamayı döndürür. Alan için ek açıklamayı alıyoruz ve onu mükemmel bir şekilde görebiliyoruz.
-
getGenericType, parametreleştirilmiş bir türü doğru şekilde görüntülemenizi sağlar.
-
getAnnotations, nesnemize uygulanan açıklamaları döndürür.
Bu, sınıfımızdaki her alanla ilgili tüm verileri, erişim değiştiricilerini, ek açıklamalarını ve veri türlerini bu şekilde kolayca alabiliriz.
java.lang.reflect.Method sınıfı
Süper! Sınıfımızın alanlarından bahsettik. Şimdi yöntemler hakkında konuşma zamanı.
Bir Method nesnesi elde etmek için getMethod yöntemini çağırıp ona yöntemimizin adını veririz. Bu, bir Method nesnesi elde etmenin temel yoludur :
Method getNameMethod = Person.class.getMethod("getName");
Sınıfımızla çalışmaya devam edeceğiz. Alıcıları ve ayarlayıcıları ve hashCode, equals ve toString yöntemlerini ekleyelim :
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);
}
}
Şimdi Method sınıfını kullanarak inceleyeceğimiz bir dizi metot hazırlayalım . İşte en önemli yöntemlerin bir listesi:
Yöntem | Tanım |
---|---|
getName() | Yöntemin adını döndürür. |
getModifiers() | Bu yöntemin erişim değiştiricisini döndürür. |
getReturnType() | Yöntemin dönüş türünü döndürür. |
getGenericReturnType() | Genel yöntemleri hesaba katarak yöntemin dönüş türünü döndürür. |
getParameterTypes() | Bir dizi yöntem parametresi döndürür. |
getGenericParameterTypes() | Genel yöntemleri açıklayan bir dizi yöntem parametresi döndürür. |
getExceptionTypes() | Yöntemin oluşturabileceği istisnaları döndürür. |
getGenericExceptionTypes() | Parametreli türleri hesaba katarak yöntemin atabileceği istisnaları döndürür. |
getAnnotations() | Üst notlar da dahil olmak üzere, yöntem için notları döndürür. |
getDeclaredAnnotations() | Üst notlar hariç, yöntem için notları döndürür. |
Will sınıfımızın metotlarının bir dizisini elde etmek için şu metodu çağırabiliriz:
Method[] methods = Person.class.getDeclaredMethods();
Bize sınıfımızdaki tüm yöntemleri verecektir.
getName() ve getModifiers() yöntemleri
Her yöntemin adını almak için getName'i kullanabiliriz :
static List<String> getMethodsName(Method[] methods) {
return Arrays.asList(methods)
.stream()
.map(Method::getName)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}
Şimdi değiştiricileri almak için getModifiers kullanan bir yöntem yazalım :
static List<String> getModifiers(Method[] methods) {
return Arrays
.stream(methods)
.map(Method::getModifiers)
.map(String::valueOf)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}
İşte ana yöntemimiz:
public static void main(String[] args) {
Method[] methods = Person.class.getDeclaredMethods();
System.out.println(getMethodsName(methods));
System.out.println(getModifiers(methods));
}
Bizim sonucumuz:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Tüm yöntemlerimiz genel değiştiriciye sahiptir, bu nedenle son yöntem bir dizi döndürür. Kodumuzu değiştirirsek, değiştiricilerimizin kendilerini görürüz:
public static void main(String[] args) {
Method[] methods = Person.class.getDeclaredMethods();
System.out.println(getMethodsName(methods));
System.out.println(modifyModifiers(getModifiers(methods)));
}
public, public, public, public, public, public, public, public, public, public, public]
getReturnedType()
Bu yöntem, yöntemin dönüş türünü almamızı sağlar:
static void getReturnedType(Method[] methods) {
Arrays.stream(methods)
.map(Method::getReturnType)
.forEach(System.out::println);
}
boole
sınıfı java.lang.String
int
geçersiz
sınıf java.lang.String
boolean
int
geçersiz
geçersiz
geçersiz
getGenericReturnType()
Person sınıfımıza, parametreleştirilmiş bir türe sarılmış türü döndüren bir yöntem verelim ve dönüş değerini almaya çalışalım:
public List<String> someMethod() {
// Very useful and important method
return null;
}
Ve ana yöntemimizi güncelleyeceğiz:
static void getGenericReturnType(Method[] methods) {
Arrays.stream(methods)
.map(Method::getGenericReturnType)
.forEach(System.out::println);
}
Yöntemimizin sonucu:
boole
sınıfı java.lang.String
int
geçersiz
sınıf java.lang.String
boolean
int
geçersiz
geçersiz
geçersiz
java.util.List<java.lang.String>
getParameterTypes() ve getGenericParameterTypes() yöntemleri
İki yöntem daha ekleyerek Person sınıfımızı değiştirmeye devam ediyoruz :
public List<String> someMethod(List<String> list, String s) {
// Very useful and important method
return null;
}
İlki, metotlarımızın parametrelerini almamıza izin verecek ve ikincisi de bize parametreleştirilmiş tipler verecek.
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);
}
}
Yöntemlerimizden yalnızca birine erişeceğiz. Belirli bir ada sahip bir yönteme erişmek için getMethod'u çağırır ve istediğimiz yöntemin adını ve parametrelerini iletiriz:
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);
}
Kodumuzu çalıştırarak, yöntemlerin nasıl farklılaştığını ve ne döndürdüğünü göreceğiz:
sınıfı
Java.lang.String Java.util.List<java.lang.String>
sınıfı Java.lang.String
getExceptionTypes() ve getGenericExceptionTypes() yöntemleri
Bu yöntemleri, yöntemimizin atabileceği bir dizi istisna ve ayrıca (varsa) parametreleştirilmiş türlerle istisnalar elde etmek için kullanabiliriz. Gizli statik sınıfı olan yeni bir örnek kullanalım:
private static class Processor {
private void init() {}
private void process() throws IOException {}
}
Ve İşlemci sınıfımızdaki yöntemleri çağıracağız :
public static void main(String... args) throws NoSuchMethodException {
Method method = Processor.class.getDeclaredMethod("process");
Type[] type = method.getExceptionTypes();
System.out.println(Arrays.toString(type));
}
Şimdi istisnamızı görebiliriz:
Şimdi türü parametrelendirelim. Ana sınıfımızı değiştireceğiz:
private static class Processor<E extends IOException> {
private void process() throws E {
}
}
Ve ana yöntemin kodu :
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);
}
}
}
}
Bu yöntemin içinde, tür değişkenleri için genel bir üst arabirim olan TypeVariables nesnesine sahibiz . Ve bunun içinde artık dahili parametreyi, yani yuvalanmış istisnamızı alabiliriz:
sınıfı java.io.IOException
getAnnotations() ve getDeclaredAnnotations() yöntemleri
Bu yeni sınıfı kullanmaya devam edelim ve ona birkaç açıklama ekleyelim. Kendi Ek Açıklama ek açıklamamızı oluşturacağız :
@Retention(RetentionPolicy.RUNTIME)
@interface Annotation {
public String key();
public String value();
}
Ve bunu yöntemimize uygulayın:
@Annotation(key = "key", value = "value")
private void process() throws E{
}
Ve elbette tüm ek açıklamalarımızı görüntülemek için bir yöntem ekleyeceğiz:
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();
}
}
Ana yöntemimizin uygulanması :
public static void main(String... args) {
Class clazz = Processor.class;
getMethodAnnotations(clazz);
}
Ortaya çıkan ekran çıktısı:
[@com.company.Main&Annotation(key="key", value="value")]
Metotlarımıza uygulanan ek açıklamaları bu şekilde alabiliriz ve getAnnotations yöntemi, sınıfın üst açıklamalarına da erişmemizi sağlar.
Bugün, yansımanın yöntemler ve alanlarla nasıl çalışabileceğini ve onunla hangi verileri elde edebileceğimizi öğrendik!
GO TO FULL VERSION