예시 클래스의 형태는 다음과 같이 상속 구조로 구성되어 있으며, 다양한 접근제한을 설정해두었다. 필드만 살펴볼 것이므로 다른 내용들은 추가하지 않았다.
Book.java
package com.hacademy.reflection4;
public class Book {
private String publisher;
int pages;
protected String name;
public String genre;
}
Novel.java
package com.hacademy.reflection4;
import java.util.Date;
public class Novel extends Book{
private String serial;
Date publishDate;
protected int price;
public String comment;
@Override
public String toString() {
return "Novel [serial=" + serial + ", publishDate=" + publishDate + ", price=" + price + ", comment=" + comment + "]";
}
}
예제 - 필드 목록 확인
package com.hacademy.reflection4;
import java.lang.reflect.Field;
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> c = Class.forName("com.hacademy.reflection4.Novel");
System.out.println("<Accessible field list>");
for(Field field : c.getFields()) {
System.out.println(field);
}
System.out.println();
System.out.println("<Declared field list>");
for(Field field : c.getDeclaredFields()) {
System.out.println(field);
}
}
}
Novel 클래스의 필드를 조회하는 코드이다.
c.getFields()를 통해 Novel 클래스가 접근 가능한 모든 필드의 정보를 조회할 수 있다. 이 중에는 Book 클래스에서 상속받은 항목 중 접근 가능한 genre 변수가 포함된다.
c.getDeclaredFields()를 통해 Novel 클래스에 명시된 모든 필드의 정보를 조회할 수 있다. Novel 클래스의 필드만 조회된다.
결과 화면 콘솔
<Accessible field list>
public java.lang.String com.hacademy.reflection4.Novel.comment
public java.lang.String com.hacademy.reflection4.Book.genre
<Declared field list>
private java.lang.String com.hacademy.reflection4.Novel.serial
java.util.Date com.hacademy.reflection4.Novel.publishDate
protected int com.hacademy.reflection4.Novel.price
public java.lang.String com.hacademy.reflection4.Novel.comment
예제 - 이름을 지정하여 필드 조회
package com.hacademy.reflection4;
import java.lang.reflect.Field;
public class Test02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
Class<?> c = Class.forName("com.hacademy.reflection4.Novel");
Field f1 = c.getField("genre");
System.out.println(f1);
// Field f2 = c.getField("serial");//NoSuchFieldException 발생
// System.out.println(f2);
// Field f3 = c.getDeclaredField("genre");//NoSuchFieldException 발생
// System.out.println(f3);
Field f4 = c.getDeclaredField("serial");
System.out.println(f4);
}
}
이름을 통해 필드에 접근하고 싶다면 c.getField() 또는 c.getDeclaredField() 메소드를 호출한다.
c.getField()는 상속된 필드를 포함하여 접근 가능한 필드를 이름으로 조회할 수 있으며, 접근이 불가능하거나 존재하지 않는 필드명인 경우 NoSuchFieldException이 발생한다.
c.getDeclaredField()는 상속을 제외한 현재 클래스에 명시된 모든 필드 중 지정한 이름의 필드를 조회할 수 있으며, 존재하지 않는 필드명일 경우 NoSuchFieldException이 발생한다.
예제 - 객체 필드 설정
package com.hacademy.reflection4;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException{
Class<?> c = Class.forName("com.hacademy.reflection4.Novel");
Novel novel = new Novel();
Field serial = c.getDeclaredField("serial");
serial.setAccessible(true);
serial.set(novel, "TEST-SERIAL");
Field publishDate = c.getDeclaredField("publishDate");
publishDate.set(novel, new Date());
Field price = c.getDeclaredField("price");
price.set(novel, 5000);
Field comment = c.getDeclaredField("comment");
comment.set(novel, "테스트용 서적 정보");
System.out.println(novel);
}
}
위 코드는 객체를 생성한 뒤 Java Reflection을 사용하여 setter 없이 데이터를 설정하는 코드이다. private 항목까지 설정할 수 있어 기본 접근제한이 적용되지 않는다. 다만, 현재 코드 위치에서 접근이 불가능한 항목인 경우 field.setAccessible(true);를 통해 접근이 가능하도록 설정해야 필드의 항목을 설정할 수 있다.
코드 중 serial 필드는 private 접근제이므로 접근 허용 설정을 추가하였다.
Field serial = c.getDeclaredField("serial");
serial.setAccessible(true);
serial.set(novel, "TEST-SERIAL");