2022. 12. 15. 19:05ㆍ자바멘토링
먼저 !
java.lang.class객체 대해서 알아보기
class클래스
- 자바는 클래스와 인터페이스의 메타 데이터를 class클래스로 관리
- 메타 데이터: 타입이름 및 파일 경로 정보, 필드정보 , 메소드 정보
클래스 객체 얻는 방법
package main231;
public class Car {
public static void main(String[] args) {
}
}
package main231;
public class ClassExample {
public static void main(String[] args) throws ClassNotFoundException {
//클래스 부터 얻는 방법
Class clazz = Car.class;
/* Class clazz1 = Class.forName("Car"); */
//객체로 부터 얻는 방법
Car car = new Car();
Class clazz2 = car.getClass();
/* System.out.println(clazz==clazz1); */
System.out.println(clazz==clazz2);
System.out.println(clazz.getName()); // 전체 경로 얻기
System.out.println(clazz.getSimpleName()); // 클래스 이름 얻기
System.out.println(clazz.getPackage().getName());//클래스 패키지 이름 얻기
}
}
true
main231.Car
Car
main231
궁금증?
new연산자 없이 Class객체를 이용하면 좋은점은 무엇인가
: 동적으로 객체 생성이 가능해진다, 코드 작성시에 클래스 이름을 결정할 수 없고, 런타임시에 클래스 이름이 결정되는 경우에 유용하다.
참고:https://www.youtube.com/watch?v=IEs-pnSXvoU
Reflection이란?
:반사 , 반영된 이미지
실체 = Class
거울 = jvm 메모리 영역

class :
-실행중인 자바 어플리케이션의 클래스와 인터페이스의 정보를 가진 클래스
-public 생성자가 존재하지 않는다.
-class객체는jvm에 의해 자동으로 생성된다.
class의 기능들
- 클래스에 붙은 어노테이션 조회
- 클래스 생성자 조회
- 클래스 필드 조회
- 클래스 메소드 조회
- 부모 클래스, 인터페이스 조회
리플랙션은 힙 영역에 로드된 Class타입의 객체를 통해 , 원하는 클래스의 인스턴스를 생성 할수 있도록 지원하고, 인스턴스의 필드와 메소드를 접근 제어자와 상관없이 사용할 수 있도록 지원하는API이다.
여기서 로드된 클래스라고 함은,JVM의 클래스 로더에서 클래스 파일에 대한 로딩을 완료한 후 , 해당 클래스의 정보를 담은 Class타입의 객체를 생성하여 메모리의 힙 영역에 저장해 둔 것을 의미한다.
new 키워드를 통해 만드는 객체와는 다른 것임을 유의하자
리플렉션 예제
package main231;
public class Dog {
private static final String CATEGORY ="동물";
private String name;
public int age;
private Dog() {
this.name = "누렁이";
this.age=0;
}
public Dog(final String name) {
this.name =name;
this.age =0;
}
public Dog(final String name, final int age) {
this.name=name;
this.age=age;
}
//메소드
private void speak(final String sound, final int count) {
System.out.println(sound.repeat(count));
}
public void eate() {
System.out.println("사료를 먹습니다.");
}
public int getAgs() {
return age;
}
}
package main231;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Sample {
public static void main(String[] args) throws Exception {
Class<?> clazz = Dog.class;
Constructor<?> constructor1 = clazz.getDeclaredConstructor();//기본생성자를 Constructor 객체로 가져올수 있다.
Constructor<?> constructor2 = clazz.getDeclaredConstructor(String.class);// 파라미터 값
Constructor<?> constructor3 = clazz.getDeclaredConstructor(String.class,int.class);//두가지 타입의 파라미터 값을 가진 생성자 가져올수 있다.
//생성자로 객체를 생성
//Object dog1 = constructor1.newInstance(); //하지만 생성자가 접근제어자라 private이라 접근이 불가
//접근 제어자가 public이 아닌 경우 setAccessible 메소드를 이용하면 접근 할 숭있다.
constructor1.setAccessible(true);
Object dog1 =constructor1.newInstance();
Object dog2 =constructor2.newInstance("호두");
Object dog =constructor3.newInstance("호두",5);
//필드 접근
Field [] fields = clazz.getDeclaredFields();
for(Field field : fields) {
field.setAccessible(true);
System.out.println(field);
System.out.println(field.get(dog));
System.out.println("------------------------");
}
//private 필드의 값도 변경 할 수 있다.
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
System.out.println("기존:" + field.get(dog));
field.set(dog, "땅콩");
System.out.println("변경: " + field.get(dog));
//필드에 정의 된 메소드 가져오기
Method[] methods = clazz.getDeclaredMethods();
for(Method method : methods) {
method.setAccessible(true);
System.out.println(method);
System.out.println("----------------------------");
}
Method method = clazz.getDeclaredMethod("speak", String.class ,int.class);
method.setAccessible(true);
method.invoke(dog, "멍멍!",5);
}
}
private static final java.lang.String main231.Dog.CATEGORY
동물
------------------------
private java.lang.String main231.Dog.name
호두
------------------------
public int main231.Dog.age
5
------------------------
기존:호두
변경: 땅콩
private void main231.Dog.speak(java.lang.String,int)
----------------------------
public int main231.Dog.getAgs()
----------------------------
public void main231.Dog.eate()
----------------------------
멍멍!멍멍!멍멍!멍멍!멍멍!
Class 객체에 필드(메소드,변수) 의 접근제어자와 메소드 이름 매개변수 타입을 알수 있다.
리플렉션이 사용되는 곳
-인텔리 제이의 자동 완성 기능
궁금증?
리플렉션 왜 필요한가?
:
리플렉션으로 객체를 생성 할 수 있다고 했는데 생성자가 있음에도 기본 생성자가 꼭 필요한 이유?
:기본 생성자로 객체를 생성하고 필드를 통해 값을 넣어주는 것이 가장 간단한 방법이다.
라이브러리나 , 프레임 워크가 어떤 생성자를 사용할지 고르기 어렵다.
생성자에 로직이 있는 경우 원하는 값을 필드에 바로 넣어 줄 수 없다.
파라미터들의 타입이 같은 경우 필드와 이름이 다르면 값을 알맞게 넣어주기 힘들다.
기본 생성자를 사용할 경우 이 모든 경우의 수들을 고려하지 않아도된다.
(기본 생성자로 객체를 생성한 뒤 필드 이름에 맟줘 알맞은 값을 넣어주면 된다.)
어노테이션
: 주석에 불과 해 보이지만 이것 또한도 리플렉션을 통해 가능하다.
- 리플렉션을 통해 클래스나 메소드, 파라미터 정보를 가져온다.
- 리플렉션의 getAnnotation(s) , getDeclaredAnnotation(s)등의 메소드를 통해 원하는 어노테이션이 붙어 있는지 확인한다.
- 어노테이션이 붙어 있다면 원하는 로직을 수행한다.
참고:https://steady-coding.tistory.com/609
[Java] Reflection 개념 및 사용 방법
java-study에서 스터디를 진행하고 있습니다. Reflection이란? 리플렉션은 힙 영역에 로드된 Class 타입의 객체를 통해, 원하는 클래스의 인스턴스를 생성할 수 있도록 지원하고, 인스턴스의 필드와 메
steady-coding.tistory.com
에서 리플렉션 또는 원본 생성을 선택하는 방법 System.Text.Json
에서 리플렉션 또는 원본 생성을 선택하는 방법을 알아봅니다 System.Text.Json.
learn.microsoft.com
이해 안되는것 : 왜 생성자를 생성 해야 하는가?, 왜 꼭 리플렉션을 해야 하는가?, 리플렉션과 어노테이션은 무슨관계이며, json역직렬화 , 직렬화하고는 무슨 관계인가?,,,, 어떻게 스프링은 런타임시 di가 가능한가?
왜?new로 생성하면 안되는가?
'자바멘토링' 카테고리의 다른 글
리플렉션을 이용한 json 직렬화 (0) | 2022.12.28 |
---|---|
파일디스크립터 (0) | 2022.12.18 |
Try - With - Resource (0) | 2022.12.04 |
추상클래스 (0) | 2022.12.03 |
Weak Reference & Soft reference (0) | 2022.12.03 |