Constructor

Constructor(생성자) 제어

이 문서에서는 Java Reflection을 이용하여 생성자 정보를 얻어내고 객체를 생성하는 방법을 다룬다.

클래스의 형태

예제에서 사용할 클래스의 형태는 다음과 같다. 다양한 생성자를 추가해두었고, 접근제한 확인을 위해 기본생성자를 private 처리해두었다.

package com.hacademy.reflection5;

public class Product {
	private String name;
	private String type;
	private int price;
	
	private Product() {
		this("미설정", "없음", 0);
	}
	public Product(String name) {
		this(name, "없음", 0);
	}
	public Product(String name, String type) {
		this(name, type, 0);
	}
	public Product(String name, String type, int price) {
		this.name = name;
		this.type = type;
		this.price = price;
	}
	
	@Override
	public String toString() {
		return "Product [name=" + name + ", type=" + type + ", price=" + price + "]";
	}
}

예제 - 생성자 목록 불러오기

package com.hacademy.reflection5;

import java.lang.reflect.Constructor;

public class Test01 {
	public static void main(String[] args) throws ClassNotFoundException {
		Class<?> c = Class.forName("com.hacademy.reflection5.Product");
		
		System.out.println("<Accessible constructor list>");
		for(Constructor<?> constructor : c.getConstructors()) {
			System.out.println(constructor);
		}
		
		System.out.println("<Declared constructor list>");
		for(Constructor<?> constructor : c.getDeclaredConstructors()) {
			System.out.println(constructor);
		}
	}
}

생성자 목록을 조회할 수 있는 명령은 두 가지가 있다.

  • class.getConstructors() - 접근 가능한 생성자 목록을 조회

  • class.getDeclaredConstructors() - 모든 생성자 목록을 조회

예제 - 생성자를 정하여 불러오기

package com.hacademy.reflection5;

import java.lang.reflect.Constructor;

public class Test02 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
		Class<?> c = Class.forName("com.hacademy.reflection5.Product");
		
		//Constructor<?> c1 = c.getConstructor();//error
		Constructor<?> c2 = c.getConstructor(String.class);
		Constructor<?> c3 = c.getConstructor(String.class, String.class);
		Constructor<?> c4 = c.getConstructor(String.class, String.class, int.class);
		
		Constructor<?> c5 = c.getDeclaredConstructor();
		Constructor<?> c6 = c.getDeclaredConstructor(String.class);
		Constructor<?> c7 = c.getDeclaredConstructor(String.class, String.class);
		Constructor<?> c8 = c.getDeclaredConstructor(String.class, String.class, int.class);
		
		System.out.println("c2 = " + c2);
		System.out.println("c3 = " + c3);
		System.out.println("c4 = " + c4);
		System.out.println("c5 = " + c5);
		System.out.println("c6 = " + c6);
		System.out.println("c7 = " + c7);
		System.out.println("c8 = " + c8);
	}
}

생성자를 불러올 때는 형태를 지정하여 불러온다. 다음 두 가지 명령이 존재한다.

  • class.getConstructor(형태) - 접근 가능한 생성자 중 형태에 맞는 생성자 객체를 반환. 없으면 NoSuchMethodException 발생

  • class.getDeclaredConstructor(형태) - 모든 생성자 중 형태에 맞는 생성자 객체를 반환. 없으면 NoSuchMethodException 발생

예제 - 기본 생성자를 이용한 객체 생성

package com.hacademy.reflection5;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test03 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<?> c = Class.forName("com.hacademy.reflection5.Product");
		Constructor<?> constructor = c.getDeclaredConstructor();
		constructor.setAccessible(true);
		Product product = (Product) constructor.newInstance();
		System.out.println(product);
	}
}

생성자 객체에 있는 .newInstance() 메소드를 호출하면 인스턴스를 생성할 수 있다.

예제 클래스인 Product에서는 기본 생성자가 private이기 때문에 생성 전 .setAccessible(true) 설정이 필요하다.

constructor.setAccessible(true);

생성 시 인스턴스가 Object 형태로 반환되므로 생성한 형태에 맞게 Down-casting 해주어야 한다.

Product product = (Product) constructor.newInstance();

예제 - 매개변수 (String) 생성자 이용한 객체 생성

package com.hacademy.reflection5;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test04 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<?> c = Class.forName("com.hacademy.reflection5.Product");
		Constructor<?> constructor = c.getDeclaredConstructor(String.class);
		Product product = (Product) constructor.newInstance("컴퓨터");
		System.out.println(product);
	}
}

이전 예제와 다른 점은 다음과 같다.

  • 생성자가 접근 가능하므로 .setAccessible(true)를 사용하지 않음

  • 생성자 정보 검색 시 형태를 지정

  • 객체 생성 시 생성자 형태에 맞는 데이터 전달

예제 - 매개변수 (String, String) 생성자 이용한 객체 생성

package com.hacademy.reflection5;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test05 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<?> c = Class.forName("com.hacademy.reflection5.Product");
		Constructor<?> constructor = c.getDeclaredConstructor(String.class, String.class);
		Product product = (Product) constructor.newInstance("컴퓨터", "전자제품");
		System.out.println(product);
	}
}

예제 - 매개변수 (String, String, int) 생성자 이용한 객체 생성

package com.hacademy.reflection5;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test06 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<?> c = Class.forName("com.hacademy.reflection5.Product");
		Constructor<?> constructor = c.getDeclaredConstructor(String.class, String.class, int.class);
		Product product = (Product) constructor.newInstance("컴퓨터", "전자제품", 1500000);
		System.out.println(product);
	}
}

Last updated