> For the complete documentation index, see [llms.txt](https://docs.sysout.co.kr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sysout.co.kr/base-language/java/java-advanced/java-reflection/field.md).

# Field

## Field 제어

이 문서에서는 [<mark style="color:blue;">Java Reflection</mark>](/base-language/java/java-advanced/java-reflection.md)을 이용하여 필드를 제어하는 방법에 대해서 살펴본다.

### 클래스의 형태

예시 클래스의 형태는 다음과 같이 상속 구조로 구성되어 있으며, 다양한 접근제한을 설정해두었다. 필드만 살펴볼 것이므로 다른 내용들은 추가하지 않았다.

{% code title="Book.java" %}

```java
package com.hacademy.reflection4;

public class Book {
	private String publisher;
	int pages;
	protected String name;
	public String genre;
}
```

{% endcode %}

{% code title="Novel.java" %}

```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 + "]";
	}
}

```

{% endcode %}

### 예제 - 필드 목록 확인

```java
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 클래스의 필드만 조회된다.

{% code title="결과 화면 콘솔" %}

```
<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
```

{% endcode %}

### 예제 - 이름을 지정하여 필드 조회

```java
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()`는 상속된 필드를 포함하여 접근 가능한 필드를 이름으로 조회할 수 있으며, 접근이 불가능하거나 존재하지 않는 필드명인 경우 <mark style="color:red;">NoSuchFieldException</mark>이 발생한다.

`c.getDeclaredField()`는 상속을 제외한 현재 클래스에 명시된 모든 필드 중 지정한 이름의 필드를 조회할 수 있으며, 존재하지 않는 필드명일 경우 <mark style="color:red;">NoSuchFieldException</mark>이 발생한다.

### 예제 - 객체 필드 설정

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

위 코드는 객체를 생성한 뒤 <mark style="color:blue;">Java Reflection</mark>을 사용하여 setter 없이 데이터를 설정하는 코드이다. private 항목까지 설정할 수 있어 기본 접근제한이 적용되지 않는다. 다만, 현재 코드 위치에서 접근이 불가능한 항목인 경우 `field.setAccessible(true);`를 통해 접근이 가능하도록 설정해야 필드의 항목을 설정할 수 있다.

코드 중 serial 필드는 <mark style="color:red;">private 접근제</mark>이므로 접근 허용 설정을 추가하였다.

```java
Field serial = c.getDeclaredField("serial");
serial.setAccessible(true);
serial.set(novel, "TEST-SERIAL");
```

반대로 데이터를 추출하고 싶은 경우에는 `field.get()` 을 이용한다.
