java.lang.reflect.Field 클래스
Field 클래스 는 클래스 또는 인터페이스의 단일 필드에 대한 정보 및 동적 액세스를 제공합니다. Field는 get 또는 set 액세스 작업 중에 확장 유형 변환을 허용하지만 축소가 발생하면 IllegalArgumentException이 발생합니다.
Field 객체를 얻으려면 먼저 클래스를 작성합니다.
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 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);
}
}
이것이 나중에 작업할 클래스의 필드 목록을 얻는 방법입니다. 결과는 다음과 같습니다.
이제 이 데이터로 무엇을 할 수 있는지 알아봅시다. Field 클래스 의 메서드에 대해 이야기해 봅시다 .
방법 | 설명 |
---|---|
getType() | 이 필드가 나타내는 필드의 선언된 유형을 식별하는 클래스 객체를 반환합니다.필드물체. |
getAnnotatedType() | 반환주석 유형이 Field가 나타내는 필드의 선언된 유형을 지정하기 위해 유형의 사용을 나타내는 개체입니다. |
getGenericType() | 반환유형this가 나타내는 필드의 선언된 유형을 나타내는 객체필드물체. |
getName() | 이 표시되는 필드의 이름을 반환합니다.필드물체. |
getModifiers() | 이 항목이 나타내는 필드에 대한 Java 언어 수정자를 인코딩하는 int를 반환합니다.필드물체. |
getAnnotations() | 이 필드에 대한 주석을 반환합니다. 주석이 없으면 빈 배열을 반환합니다. |
getType(), getName() 및 getModifiers() 메서드
getType() 메서드를 사용하여 필드의 유형을 가져올 수 있습니다. 방법을 작성해 봅시다:
static void printTypes(List<Field> fields){
fields.forEach(e -> System.out.println(e.getType()));
}
결과는 다음과 같습니다.
int
부울
클래스 java.lang.String
int
int
이제 클래스에 필드 이름을 가져오는 메서드를 추가해 보겠습니다. 이렇게 하면 클래스의 필드를 더 쉽게 탐색할 수 있습니다.
static void printTypesAndNames(List<Field> fields){
fields.forEach(e -> System.out.printf("Field type - %s\nField name - %s\n\n", e.getType(), e.getName()));
}
이제 결과가 더 이해하기 쉽습니다.
필드 이름 - name
필드 유형 - int
필드 이름 - age
필드 유형 - boolean
필드 이름 - isMale
필드 유형 - class java.lang.String
필드 이름 - address
필드 유형 - int
필드 이름 - MAX_AGE
필드 유형 - int
필드 이름 - MIN_AGE
엄청난! 방법을 좀 더 수정해 봅시다! 여기에 액세스 수정자를 추가합니다.
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())));
}
그리고 e.getModifiers() 가 반환하는 것을 살펴보겠습니다 . 이 메서드는 필드의 액세스 한정자의 상태를 결정할 수 있는 int를 반환합니다. Modifier 클래스에는 필드의 각 특정 수정자를 담당하는 정적 변수가 포함되어 있습니다 .
반환 값을 Modifier.toString() 에 래핑 하고 즉시 값을 텍스트로 가져옵니다.
필드 이름 - 이름
수정자 - 개인
필드 유형 - int
필드 이름 - 나이
수정자 - 개인
필드 유형 - 부울
필드 이름 - isMale
수정자 - 공개
필드 유형 - 클래스 java.lang.String
필드 이름 - 주소
수정자 - 보호된
필드 유형 - int
필드 이름 - MAX_AGE
수정자 - public static final
필드 유형 - int
필드 이름 - MIN_AGE
수정자 - public static final
Modifier.toString() 이 없는 모습은 다음과 같습니다 .
필드 이름 - 이름
수정자 - 2
필드 유형 - int
필드 이름 - 연령
수정자 - 2
필드 유형 - 부울
필드 이름 - isMale
수정자 - 1
필드 유형 - 클래스 java.lang.String
필드 이름 - 주소
수정자 - 4
필드 유형 - int
필드 이름 - MAX_AGE
수정자 - 25
필드 유형 - int
필드 이름 - MIN_AGE
수정자 - 25
getAnnotations(), getAnnotatedType() 및 getGenericType() 메서드
이러한 메서드와 함께 작동하도록 Person 클래스를 수정해 보겠습니다 . 자체 주석을 작성하여 필드에 적용합니다. 그리고 필드를 몇 개 더 추가합니다.
두 개의 주석을 만들어 보겠습니다. Pig Latin의 변수 이름을 하나에 전달하고 두 번째는 요소에 사용합니다.
@Target(value=ElementType.FIELD)
@Retention(value= RetentionPolicy.RUNTIME)
public @interface Name {
String name();
}
@Target({ ElementType.TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Number {
}
그리고 메인 클래스와 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())));
}
우리 방법의 결과를 살펴보고 그것이 무엇을 위한 것인지 알아낼 때입니다.
java.lang.Class<java.lang.Object>
java.util.List<java.lang.String>
java.lang.String
int @Number()[]
getGenericType:
java.lang.Class<java.lang. 객체>
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")]
[@이름(이름="\u0041\u006d\u0065\u002d\u006e\u0061\u0079")] [
]
-
getAnnotatedType은 주어진 필드에 대한 주석을 반환합니다(있는 경우). 필드에 대한 주석을 얻었고 완벽하게 볼 수 있습니다.
-
getGenericType을 사용하면 매개변수화된 유형을 올바르게 표시할 수 있습니다.
-
getAnnotations는 개체에 적용된 주석을 반환합니다.
이것은 클래스의 각 필드에 대한 모든 데이터와 액세스 수정자, 주석 및 데이터 유형을 쉽게 얻을 수 있는 방법입니다.
java.lang.reflect.Method 클래스
감독자! 우리는 우리 수업의 분야에 대해 이야기했습니다. 이제 방법에 대해 이야기할 시간입니다.
Method 객체를 얻으려면 getMethod 메서드를 호출하여 메서드 이름을 전달합니다. 이것은 Method 객체를 얻는 기본 방법입니다 .
Method getNameMethod = Person.class.getMethod("getName");
우리는 계속해서 우리 학급과 함께 일할 것입니다. getter 및 setter, hashCode, equals 및 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);
}
}
이제 Method 클래스 를 사용하여 검사할 일련의 메서드를 준비하겠습니다 . 다음은 가장 중요한 방법 목록입니다.
방법 | 설명 |
---|---|
getName() | 메서드의 이름을 반환합니다. |
getModifiers() | 이 메서드의 액세스 한정자를 반환합니다. |
getReturnType() | 메서드의 반환 유형을 반환합니다. |
getGenericReturnType() | 제네릭 메서드를 설명하는 메서드의 반환 유형을 반환합니다. |
getParameterTypes() | 메서드 매개변수의 배열을 반환합니다. |
getGenericParameterTypes() | 제네릭 메서드를 설명하는 메서드 매개 변수 배열을 반환합니다. |
getExceptionTypes() | 메서드가 throw할 수 있는 예외를 반환합니다. |
getGenericExceptionTypes() | 매개변수화된 유형을 고려하여 메서드가 throw할 수 있는 예외를 반환합니다. |
getAnnotations() | 부모 주석을 포함하여 메서드에 대한 주석을 반환합니다. |
getDeclaredAnnotations() | 부모 주석을 제외한 메서드의 주석을 반환합니다. |
클래스의 메서드 배열을 얻으려면 다음 메서드를 호출할 수 있습니다.
Method[] methods = Person.class.getDeclaredMethods();
클래스의 모든 메서드를 제공합니다.
getName() 및 getModifiers() 메서드
getName을 사용하여 각 메서드의 이름을 가져올 수 있습니다 .
static List<String> getMethodsName(Method[] methods) {
return Arrays.asList(methods)
.stream()
.map(Method::getName)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}
이제 수정자를 가져오기 위해 getModifiers를 사용하는 메서드를 작성해 보겠습니다 .
static List<String> getModifiers(Method[] methods) {
return Arrays
.stream(methods)
.map(Method::getModifiers)
.map(String::valueOf)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}
주요 방법은 다음과 같습니다 .
public static void main(String[] args) {
Method[] methods = Person.class.getDeclaredMethods();
System.out.println(getMethodsName(methods));
System.out.println(getModifiers(methods));
}
우리의 결과:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
모든 메서드에는 public 한정자가 있으므로 마지막 메서드는 1의 배열을 반환합니다. 코드를 수정하면 수정자 자체가 표시됩니다.
public static void main(String[] args) {
Method[] methods = Person.class.getDeclaredMethods();
System.out.println(getMethodsName(methods));
System.out.println(modifyModifiers(getModifiers(methods)));
}
공개, 공개, 공개, 공개, 공개, 공개, 공개, 공개, 공개, 공개, 공개]
getReturnedType()
이 메서드를 사용하면 메서드의 반환 유형을 얻을 수 있습니다.
static void getReturnedType(Method[] methods) {
Arrays.stream(methods)
.map(Method::getReturnType)
.forEach(System.out::println);
}
부울
클래스 java.lang.String
int
void
클래스 java.lang.String
부울
int
void
void
void
getGenericReturnType()
Person 클래스에 매개변수화된 유형으로 래핑된 유형을 반환하는 메서드를 제공 하고 반환 값을 가져오도록 합시다.
public List<String> someMethod() {
// Very useful and important method
return null;
}
그리고 우리는 우리의 주요 방법을 업데이트할 것입니다:
static void getGenericReturnType(Method[] methods) {
Arrays.stream(methods)
.map(Method::getGenericReturnType)
.forEach(System.out::println);
}
우리 방법의 결과:
부울
클래스 java.lang.String
int
void
클래스 java.lang.String
부울
int
void
void
void
java.util.List<java.lang.String>
getParameterTypes() 및 getGenericParameterTypes() 메서드
우리는 계속해서 Person 클래스를 수정하여 두 가지 메서드를 더 추가합니다.
public List<String> someMethod(List<String> list, String s) {
// Very useful and important method
return null;
}
첫 번째는 메서드의 매개변수를 가져오고 두 번째는 매개변수화된 유형도 제공합니다.
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);
}
}
우리는 우리의 방법 중 하나만 액세스할 것입니다. 특정 이름으로 메서드에 액세스하려면 getMethod를 호출 하고 원하는 메서드의 이름과 매개 변수를 전달합니다.
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);
}
코드를 실행하면 메서드가 어떻게 다른지, 반환되는 내용이 무엇인지 확인할 수 있습니다.
클래스 java.lang.String
java.util.List<java.lang.String>
클래스 java.lang.String
getExceptionTypes() 및 getGenericExceptionTypes() 메서드
이러한 메소드를 사용하여 메소드가 던질 수 있는 예외 배열과 매개변수화된 유형이 있는 예외(있는 경우)를 가져올 수 있습니다. 숨겨진 정적 클래스가 있는 새 예제를 사용하겠습니다.
private static class Processor {
private void init() {}
private void process() throws IOException {}
}
그리고 Processor 클래스 에서 메서드를 호출합니다 .
public static void main(String... args) throws NoSuchMethodException {
Method method = Processor.class.getDeclaredMethod("process");
Type[] type = method.getExceptionTypes();
System.out.println(Arrays.toString(type));
}
이제 예외를 볼 수 있습니다.
이제 유형을 매개변수화하겠습니다. 기본 클래스를 수정합니다.
private static class Processor<E extends IOException> {
private void process() throws E {
}
}
그리고 주요 방법 의 코드 :
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);
}
}
}
}
이 메서드 안에는 유형 변수에 대한 일반 부모 인터페이스인 TypeVariables 개체가 있습니다 . 그 안에 이제 내부 매개변수, 즉 중첩 예외를 가져올 수 있습니다.
클래스 java.io.IOException
getAnnotations() 및 getDeclaredAnnotations() 메서드
이 새 클래스를 계속 사용하고 몇 가지 주석을 추가해 보겠습니다. 자체 Annotation 주석을 생성합니다 .
@Retention(RetentionPolicy.RUNTIME)
@interface Annotation {
public String key();
public String value();
}
그리고 그것을 우리의 방법에 적용하십시오:
@Annotation(key = "key", value = "value")
private void process() throws E{
}
물론 모든 주석을 표시하는 방법을 추가할 것입니다.
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();
}
}
주요 방법 구현 :
public static void main(String... args) {
Class clazz = Processor.class;
getMethodAnnotations(clazz);
}
결과 화면 출력은 다음과 같습니다.
[@com.company.Main&Annotation(key="key", value="value")]
이것이 메서드에 적용된 주석을 가져올 수 있는 방법이며 getAnnotations 메서드를 사용하면 클래스의 상위 주석에도 액세스할 수 있습니다.
오늘 우리는 리플렉션이 메서드 및 필드와 함께 작동하는 방식과 이를 통해 얻을 수 있는 데이터에 대해 알게 되었습니다!
GO TO FULL VERSION