java.lang.reflect.Field class

Kelas Field menehi informasi babagan lan akses dinamis menyang lapangan siji saka kelas utawa antarmuka. Lapangan uga ngidini konversi jinis widening sak njaluk utawa nyetel operasi akses, nanging mbalang IllegalArgumentException yen narrowing bakal kelakon.

Kanggo entuk obyek Field , kita bakal nulis kelas dhisik:


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;
}

Lan iki kode kanggo nggarap kelas kasebut:


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);
    }
}

Iki carane entuk dhaptar lapangan kelas, sing bakal ditindakake mengko. Iki asile:

[private java.lang.String com.company.Person.name, private int com.company.Person.age, public boolean com.company.Person.isMale, protected java.lang.String com.company.Person.address, public static final int com.company.Person.MAX_AGE, public static final int com.company.Person.MIN_AGE]

Saiki ayo ngerteni apa sing bisa ditindakake karo data kasebut. Ayo pirembagan babagan metode kelas Lapangan :

Metode Katrangan
getType() Ngasilake obyek Kelas sing ngenali jinis ngumumaké lapangan dituduhake dening ikilapanganobyek.
getAnnotatedType() Wangsul anTipe Anotasiobyek sing makili nggunakake jinis kanggo nemtokake jinis ngumumaké saka lapangan dituduhake dening Field iki.
getGenericType() Wangsulan aJinisobyek sing makili jinis ngumumaké saka lapangan dituduhake dening ikilapanganobyek.
njalukName() Ngasilake jeneng lapangan sing diwakili dening ikilapanganobyek.
getModifiers() Ngasilake enkoding int modifiers basa Jawa kanggo lapangan dituduhake dening ikilapanganobyek.
getAnnotations() Ngasilake anotasi kanggo lapangan iki. Yen ora ana anotasi, bakal ngasilake array kosong.

metode getType(), getName(), lan getModifiers().

Kita bisa nggunakake metode getType () kanggo entuk jinis lapangan. Ayo nulis metode:


static void printTypes(List<Field> fields){
      fields.forEach(e -> System.out.println(e.getType()));
  }

Lan kita entuk asil iki:

class java.lang.String
int
boolean
class java.lang.String
int
int

Saiki ayo tambahake metode menyang kelas kanggo entuk jeneng lapangan. Iki bakal luwih gampang kanggo navigasi lapangan kelas kita.


static void printTypesAndNames(List<Field> fields){
   fields.forEach(e -> System.out.printf("Field type - %s\nField name - %s\n\n", e.getType(), e.getName()));
}

Saiki asile luwih bisa dingerteni:

Jinis kolom - kelas java.lang.String
Jeneng kolom - jeneng

Tipe kolom - int
Jeneng kolom - umur

Tipe kolom - boolean
Jeneng kolom - isMale

Tipe kolom - kelas java.lang.
String Jeneng kolom - alamat

Tipe kolom - int
Jeneng kolom - MAX_AGE

Jinis kolom - int
Jeneng kolom - MIN_AGE

apik tenan! Ayo ngowahi cara kita maneh! Kita bakal nambah modifikasi akses ing kene


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())));
}

Lan ayo kang katon ing apa e.getModifiers () bali. Cara iki ngasilake int sing ngidini kita nemtokake status modifiers akses lapangan kita. Kelas Modifier ngemot variabel statis sing tanggung jawab kanggo saben modifier tartamtu saka lapangan.

Ayo bungkus nilai bali ing Modifier.toString () lan langsung entuk nilai minangka teks:

Jinis kolom - kelas java.lang.String
Jeneng kolom - jeneng
Modifiers - pribadi

Tipe Field - int
Jeneng kolom - umur
Modifiers -

jinis Field pribadi - boolean
Jeneng Field - isMale
Modifiers -

jinis Field umum - kelas java.lang.String
jeneng Field - alamat
Modifiers -

jinis Field sing dilindhungi - int
Jeneng kolom - MAX_AGE
Modifiers - public statis final

Tipe Field - int
jeneng Field - MIN_AGE
Modifiers - public static final

Mangkene apa sing katon tanpa Modifier.toString() :

Jinis kolom - kelas java.lang.String
Jeneng kolom - jeneng
Modifiers - 2

Tipe kolom - int
Jeneng kolom - umur
Modifiers - 2

Tipe kolom - boolean
Jeneng Field - isMale
Modifiers - 1

Tipe kolom - class java.lang.String
Jeneng Field - alamat
Modifiers - 4

Field Type - int
Field Name - MAX_AGE
Modifiers - 25

Field Type - int
Field Name - MIN_AGE
Modifiers - 25

metode getAnnotations(), getAnnotatedType(), lan getGenericType().

Ayo ngowahi kelas Person kanggo nggarap metode kasebut. Kita bakal nulis anotasi dhewe lan ditrapake ing lapangan. Lan kita bakal nambah sawetara lapangan liyane.

Ayo nggawe rong anotasi. Kita bakal ngliwati jeneng variabel ing Pig Latin menyang siji, lan kita bakal nggunakake nomer loro kanggo unsur:


@Target(value=ElementType.FIELD)
@Retention(value= RetentionPolicy.RUNTIME)
public @interface Name {
    String name();
}

@Target({ ElementType.TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Number {
}

Lan kita bakal ngganti kelas utama lan kelas Person :


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())));
}

Iku wektu kanggo ndeleng asil saka cara kita lan ngerti apa iku kanggo:

getAnnotatedType:
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
class [I

getAnnotations:
[]
[@Name(name="\u0055\u0073\u0065\u0072\u0020\u006e\u0069\u0063 \u006b\u006e\u0061\u006d\u0065\u0073")]
[@Jeneng(jeneng="\u0041\u006d\u0065\u002d\u006e\u0061\u0079")] [
]
  • getAnnotatedType ngasilake anotasi kanggo lapangan sing diwenehake, yen ana. Kita entuk anotasi kanggo lapangan lan kita bisa ndeleng kanthi sampurna.

  • getGenericType ngidini sampeyan nampilake jinis parameter kanthi bener.

  • getAnnotations ngasilake anotasi sing ditrapake kanggo obyek kita.

Iki carane kita bisa gampang njaluk kabeh data bab saben lapangan ing kelas kita, uga akses modifiers, anotasi lan jinis data.

kelas java.lang.reflect.Method

Super! Kita wis ngomong babagan lapangan kelas kita. Saiki iku wektu kanggo pirembagan bab cara.

Kanggo entuk obyek Metode , kita nelpon metode getMethod , menehi jeneng metode kita. Iki minangka cara dhasar kanggo entuk obyek Metode :


Method getNameMethod =  Person.class.getMethod("getName");

Kita bakal terus nggarap kelas kita. Ayo tambahake getter lan setter, lan kode hash, padha lan metode toString :


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);
    }
}

Saiki ayo nyiyapake sakumpulan metode sing bakal ditliti nggunakake kelas Metode . Ing ngisor iki dhaptar cara sing paling penting:

Metode Katrangan
njalukName() Ngasilake jeneng metode.
getModifiers() Ngasilake modifier akses cara iki.
getReturnType() Ngasilake jinis bali saka cara.
getGenericReturnType() Ngasilake jinis bali saka cara, accounting kanggo cara umum.
getParameterTypes() Ngasilake array saka paramèter cara.
getGenericParameterTypes() Ngasilake macem-macem parameter metode, ngitung metode umum.
getExceptionTypes() Ngasilake pangecualian sing cara bisa uncalan.
getGenericExceptionTypes() Ngasilake pangecualian sing cara bisa uncalan, accounting kanggo jinis parameterized.
getAnnotations() Ngasilake anotasi kanggo metode kasebut, kalebu anotasi induk.
getDeclaredAnnotations() Ngasilake anotasi kanggo metode kasebut, ora kalebu anotasi induk.

Kanggo entuk array saka metode kelas kita, kita bisa nelpon metode iki:


Method[] methods = Person.class.getDeclaredMethods();

Iku bakal menehi kita kabeh cara ing kelas kita.

metode getName() lan getModifiers().

Kita bisa nggunakake getName kanggo njaluk jeneng saben metode:


static List<String> getMethodsName(Method[] methods) {
    return Arrays.asList(methods)
            .stream()
            .map(Method::getName)
            .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}

Saiki kanggo entuk modifiers, ayo nulis metode sing nggunakake getModifiers :


static List<String> getModifiers(Method[] methods) {
    return Arrays
            .stream(methods)
            .map(Method::getModifiers)
            .map(String::valueOf)
            .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}

Punika cara utama kita :


public static void main(String[] args) {
    Method[] methods = Person.class.getDeclaredMethods();

    System.out.println(getMethodsName(methods));
    System.out.println(getModifiers(methods));
}

Hasil kita:

[getName, padha karo, toString, hashCode, setName, getAddress, isMale, getAge, setAge, setMale, setAddress]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Kabeh cara kita duwe modifier umum , mula cara pungkasan ngasilake macem-macem. Yen kita ngowahi kode kita, kita bakal weruh modifiers dhewe:


public static void main(String[] args) {
    Method[] methods = Person.class.getDeclaredMethods();

    System.out.println(getMethodsName(methods));
    System.out.println(modifyModifiers(getModifiers(methods)));
}
[getName, padha karo, toString, hashCode, setName, getAddress, isMale, getAge, setAge, setMale, setAddress] [public, public, public, public, public, public, public,
public, public, public]

getReturnedType()

Cara iki ngidini kita entuk jinis bali saka metode:


static void getReturnedType(Method[] methods) {
    Arrays.stream(methods)
            .map(Method::getReturnType)
            .forEach(System.out::println);
}
class java.lang.String
boolean
class java.lang.String
int
void
kelas java.lang.String
boolean
int
void
void
void

getGenericReturnType()

Ayo menehi kelas Person minangka metode sing ngasilake jinis sing dibungkus ing jinis parameter, lan nyoba entuk nilai bali:


public List<String> someMethod() {
    // Very useful and important method
    return null;
}

Lan kita bakal nganyari cara utama:


static void getGenericReturnType(Method[] methods) {
    Arrays.stream(methods)
            .map(Method::getGenericReturnType)
            .forEach(System.out::println);
}

Hasil metode kita:

class java.lang.String
boolean
class java.lang.String int
void
class
java.lang.String
boolean
int
void
void java.util.List<java.lang.String>

getParameterTypes() lan getGenericParameterTypes() metode

Kita terus ngowahi kelas Person , nambah rong cara liyane:


public List<String> someMethod(List<String> list, String s) {
    // Very useful and important method
    return null;
}

Sing pisanan bakal ngidini kita entuk paramèter cara kita, lan sing nomer loro bakal menehi jinis paramèter uga.


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);
        }
}

Kita bakal ngakses mung siji saka cara kita. Kanggo ngakses metode kanthi jeneng tartamtu, kita nelpon getMethod lan pass ing jeneng lan paramèter saka cara kita arep:


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);
}

Mlaku kode kita, kita bakal weruh carane cara beda lan apa padha bali:

antarmuka java.util.List
kelas java.lang.String

java.util.List<java.lang.String>
kelas java.lang.String

metode getExceptionTypes() lan getGenericExceptionTypes().

Kita bisa nggunakake cara iki kanggo njaluk Uploaded pangecualian sing cara kita bisa uncalan, uga pangecualian karo jinis parameterized (yen ana). Ayo nggunakake conto anyar sing duwe kelas statis sing didhelikake:


private static class Processor {
    private void init() {}

    private void process() throws IOException {}
}

Lan kita bakal nelpon metode ing kelas Prosesor kita:


public static void main(String... args) throws NoSuchMethodException {
    Method method = Processor.class.getDeclaredMethod("process");
    Type[] type = method.getExceptionTypes();
    System.out.println(Arrays.toString(type));
}

Saiki kita bisa ndeleng pengecualian kita:

[kelas java.io.IOException]

Saiki ayo paramèter jinis. Kita bakal ngowahi kelas utama kita:


private static class Processor<E extends IOException> {

    private void process() throws E {
    }
}

Lan kode metode utama :


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);
            }
        }
    }
}

Ing metode iki, kita entuk obyek TypeVariables , yaiku antarmuka induk umum kanggo variabel jinis. Lan ing njero, saiki kita bisa entuk parameter internal, yaiku pengecualian nested:

[E]
kelas java.io.IOException

metode getAnnotations() lan getDeclaredAnnotations().

Ayo terus nggunakake kelas anyar iki lan nambah sawetara anotasi. Kita bakal nggawe anotasi Anotasi dhewe :


@Retention(RetentionPolicy.RUNTIME)
@interface Annotation {

    public String key();
    public String value();
}

Lan aplikasi kanggo metode kita:


@Annotation(key = "key", value = "value")
private void process() throws E{

}

Lan mesthi kita bakal nambah cara kanggo nampilake kabeh anotasi:


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();
    }
}

Implementasi metode utama kita :


public static void main(String... args) {
    Class clazz = Processor.class;
    getMethodAnnotations(clazz);
}

Output layar sing diasilake yaiku:

proses
[@com.company.Main&Annotation(key="key", value="value")]

Iki carane kita bisa njaluk anotasi sing wis diterapake ing cara kita, lan cara getAnnotations ngidini kita ngakses anotasi induk kelas uga.

Dina iki kita kenal karo carane refleksi bisa digunakake karo metode lan lapangan, lan data apa sing bisa ditindakake!