기은P
시간이 멈추는 장소
기은P
  • Programming (272)
    • 개발노트 (1)
    • FrontEnd (56)
      • ES&JS 문법 (14)
      • HTML&CSS (4)
      • React 기본 (18)
      • React 심화 (12)
      • React 이슈 (2)
      • Project 연습 (1)
      • Next.js (5)
    • Backend&Devops (33)
      • AWS (2)
      • Docker (9)
      • Jenkins (6)
      • Nginx (6)
      • Node.js (1)
      • ElasticSearch (5)
      • 프레임워크&아키텍처 (2)
      • 암호화 (0)
      • 기타 (2)
    • 알고리즘 (3)
    • C# (8)
      • WPF (8)
    • Java (51)
      • 순수 Java (18)
      • RDF&Jena (12)
      • RCP&GEF (9)
      • JMX (5)
      • JMapper (3)
      • 오류해결 (4)
    • Database (21)
      • RDBMS (9)
      • NoSQL (2)
      • TSDB (1)
      • GraphQL (1)
      • Hibernate (3)
      • 데이터베이스 이론 (4)
      • Redis (1)
    • 프로토콜 (11)
      • Netty (4)
      • gRPC (5)
      • 프로토콜 개념 (2)
    • Server (4)
      • Linux (4)
    • 2020 정보처리기사 필기 (43)
      • 목차 (1)
      • 기출문제 (1)
      • 1과목 - 소프트웨어 설계 (6)
      • 2과목 - 소프트웨어 개발 (7)
      • 3과목 - 데이터베이스 구축 (8)
      • 4과목 - 프로그래밍 언어 활용 (7)
      • 5과목 - 정보시스템 구축 관리 (10)
    • 2020 정보처리기사 실기 (31)
      • 목차 (4)
      • 기출예상문제 (19)
      • 실기요약 (8)
    • 빅데이터분석기사 필기 (4)
      • 목차 (0)
      • 필기 요약 (3)
    • 전기 공학 (1)
      • CIM (1)
    • 산업자동화시스템 (3)
      • SCADA (1)
      • OPC UA (2)
    • 디자인패턴 (1)
    • 휴지통 (0)

공지사항

  • 공지사항/포스팅 예정 항목

최근 댓글

최근 글

전체 방문자
오늘
어제

티스토리

hELLO · Designed By 정상우.
기은P

시간이 멈추는 장소

Java/순수 Java

[Java] Reflection

2020. 3. 6. 15:59
반응형

자바에서 사용하는 리플렉션은 Class와 같은 객체를 통해 정보를 분석해 내는 방법으로, 구체적인 클래스 타입을 알지 못해도 그 클래스의 메소드, 타입, 변수들을 접근할 수 있도록 해주는 자바 API다.

Reflection은, 스프링 프레임워크, 대표적 ORM 기술인 하이버네이트, jackson 라이브러리 등에 사용된다.

 

일반적으로 간단한 변수들의 클래스의 호출 과정은 아래와 같다.

public void Test1() {
		//임의의 클래스를 가져오는 방법
		Class c = "foo".getClass();
		System.out.println(c);      //class java.lang.String
		

		Class str = new String("").getClass();
		System.out.println(str);      //class java.lang.String
		

		Class i = new Integer(0).getClass();
		System.out.println(i);      //class java.lang.Integer
		
		byte[] b = new byte[1024];
		Class c1 = b.getClass();
		System.out.println(c1);     //class [B
		
		Set<String> s = new HashSet<>();
		Class c2 = s.getClass();
		System.out.println(c2);     //class java.util.HashSet
	}

 

Class 객체가 해당 클래스의 타입을 반환한다는 것은 위의 코드를 실행하면 알 수 있다.

조금 심화해보면

public class Employee implements java.io.Serializable {
	private Integer id;
	private Integer age;
	private Date birthday;
	private String name;

	public Employee() {
	}

	public Employee(Integer age, Date birthday, String name) {
		this.age = age;
		this.birthday = birthday;
		this.name = name;
	}

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Integer getAge() {
		return this.age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public Date getBirthday() {
		return this.birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

 

이와 같은 Employee 클래스가 있고, id, age, name, birthday의 변수에 관련된 Getter, Setter 메서드가 있다고 가정하고 Reflection을 사용해본다면 어떻게 될까?

 

public void Test3() {
		try {
			Class c = Employee.class;
			Method m[] = c.getDeclaredMethods(); // Class에서 정의된 메소드 리스트를 반환
			for (int i = 0; i < m.length; i++)
				System.out.println(m[i].toString());
		} catch (Throwable e) {
			System.err.println(e);

		}
	}


Employee 클래스를 가지고 와서, getDeclaredMethods()로 클래스에서 정의한 메소드 리스트를 Method 배열에 담아서 출력해보면 아래와 같은 결과가 나온다.

 

public java.lang.String org.power21.hibernate.data.Employee.getName()
public java.lang.Integer org.power21.hibernate.data.Employee.getId()
public void org.power21.hibernate.data.Employee.setName(java.lang.String)
public void org.power21.hibernate.data.Employee.setAge(java.lang.Integer)
public void org.power21.hibernate.data.Employee.setBirthday(java.util.Date)
public java.lang.Integer org.power21.hibernate.data.Employee.getAge()
public java.util.Date org.power21.hibernate.data.Employee.getBirthday()
public void org.power21.hibernate.data.Employee.setId(java.lang.Integer)

 

Getter, Setter로 정의한 메소드들이 출력된 것을 확인할 수 있다.

더 자세하게 Class와 관련된 메소드들을 살펴보면

 

	public void Test2() {
		Class c = Employee.class;
		Method[] m = c.getMethods();
		Field[] f = c.getFields();
		Constructor[] cs = c.getConstructors();
		Class[] inter = c.getInterfaces();
		Class superClass = c.getSuperclass();
		System.out.println(c); // class org.power21.hibernate.data.Employee
		System.out.println(m[0]); // public java.lang.String org.power21.hibernate.data.Employee.getName()
		System.out.println(f); // [Ljava.lang.reflect.Field;@3fee733d
		System.out.println(cs[0]); // public org.power21.hibernate.data.Employee()
		System.out.println(inter[0]); // interface java.io.Serializable
		System.out.println(superClass); // class java.lang.Object

	}

Constructor나, Interface나, Field나, Method나, SuperClass나.

Reflection은 클래스를 구성하는 요소들을 가져와서 사용할 수 있다.

 

아, Boolean 변수는 원시 코드라서 Reflection이 안된다는 점 참고하길 바란다.

 

	public void Test4() {
		Class c = Employee.class;
		boolean b1 = c.isInstance(new Integer(10)); // c가 Integer가 맞는지?
		System.out.println("결과 :: " + b1);
		boolean b2 = c.isInstance(new Employee()); // c가 Employee가 맞는지?
		System.out.println("결과 :: " + b2);		
	}

 

InstansceOf 기능도 사용할 수 있다.

isInstance(Object object)에 비교할 대상을 넣으면 boolean이 반환된다.

 

	public void Test5() {
		try {
			Class cls = Employee.class;
			Method mList[] = cls.getDeclaredMethods(); // Employee 클래스의 메소드 리스트를 가져온다.
			System.out.println("interface :: " + cls.getInterfaces()[0]); // 인터페이스			

			for (int i = 0; i < mList.length; i++) {
				Method m = mList[i];				
				System.out.println("name :: " + m.getName()); // 메소드의 이름				
				Class pvec[] = m.getParameterTypes(); // 메소드의 파라미터 타입
				for (int j = 0; j < pvec.length; j++)
					System.out.println(" param :: " + j + " " + pvec[j]);
				Class evec[] = m.getExceptionTypes(); // 메소드의 예외처리 타입
				for (int j = 0; j < evec.length; j++)
					System.out.println("exception :: " + j + " " + evec[j]);
				System.out.println("return type :: " + m.getReturnType()); // 메소드의 리턴 타입
				System.out.println(" ");
			}

		} catch (Throwable e) {
			System.err.println(e);
		}
	}

 

실질적으로 사용되는 부분은 위와 같다.

Method 리스트를 받아와서 해당 메소드 이름, 파라미터 타입, 예외처리 타입, 리턴 타입등을 알아내서 용도에 맞게 사용되도록 한다.

 

이렇게 되면 해당 클래스의 이름이나 메소드나, 파라미터를 알지 못해도 이 흐름에 이 클래스를 사용해야만 할 때 Reflecion을 이용해서 실행할 수 있다는 장점이 있다.

반응형
저작자표시 변경금지 (새창열림)

'Java > 순수 Java' 카테고리의 다른 글

[Java] Eclipse 이클립스 크롬 연동하기(Web Browser 연동)  (0) 2020.03.13
[Java] SWT Tree와 Map을 활용한 Directory 출력 예제 소스  (0) 2020.03.12
[Java] SWT Tree 사용 예제  (0) 2020.03.12
[Java] Apache log4j .properties 생성 및 오류 해결 방법  (0) 2020.03.06
[Java] Property 파일(.properties) 생성 및 사용  (0) 2020.03.05
    'Java/순수 Java' 카테고리의 다른 글
    • [Java] SWT Tree와 Map을 활용한 Directory 출력 예제 소스
    • [Java] SWT Tree 사용 예제
    • [Java] Apache log4j .properties 생성 및 오류 해결 방법
    • [Java] Property 파일(.properties) 생성 및 사용
    기은P
    기은P
    기은P의 블로그 일상과 개발 관련 포스팅 #React #Typescript #Next #Nest https://github.com/kimdongjang

    티스토리툴바