리플렉션
기존프로그램의 변경없이 완전히 동적인 코드를 짜기 위한 도구이다.
Constructor 클래스
getConstructor() -> 생성자 정보를 얻어온다.
newInstance() -> 객체 생성을 한다.
getMethods() - > 객체 내에 어떤 함수가 있는지 함수명 리스트를 받아온다.
Method 클래스
->단점 : 존재하지 않는 함수에 대해서 오류를 말하지 않는다
Constructor의 getMethods()를 통해서 함수명이 존재하는지 확인해야한다.
getMethod() - > 함수를 검색하는 메소드, if문을 통해서 함수가 있는지 확인하고 사용해야한다.
invoke() - > 함수 호출을 하는 메소드, 함수를실행할때 필요한 객체정보와 함수에 대한 인자를 전달해 주어야한다.
public int funcB(int a) {
System.out.println("Member.funcB()...");
return a;
}
public int funcB(int a, int b) {
System.out.println("Member.funcB()...");
return a + b;
}
public class MemberTest {
//프로그램을 동적으로 구현하기 위한 리플렉션
public static void main(String[] args) {
String className = args[0];//"ch12.sec03.exam05.Member";
String methodName = args[1];
try {
//클래스 정보를 로딩한다
Class cls = Class.forName(className);
//생성자 함수 정보를 얻는다
Constructor constructor = cls.getConstructor();
// 생성자 함수를 객체를 생성한다
Member obj = (Member) constructor.newInstance();
// 내가 가져온 객체에 메소드가 존재 하는지 확인해
for (Method method : cls.getMethods()) {
//이것도 객체니까 equals로 비교하고 이름이 같으면 메소드를 실행하고 종료
if (methodName.equals(method.getName())) {
//이 함수를 갖고 잇는 객체 와 함수에 대한 인자를 전달해 주어야한다.
method.invoke(obj);
break;
}
//System.out.println(method.getName());
}
Method funcA = cls.getMethod("funcA");
funcA.invoke(obj);
//매개변수가 있는 함수 불러오기
Method funcB = cls.getMethod("funcB", int.class, int.class);
//매개변수가 2개 있는 함수 실행한 결과 값 reValue에 대입
Object retValue = funcB.invoke(obj, 10, 20);
System.out.println(methodFuncB + "() 결과 -> " + retValue);
//매개변수가 있는 함수 불러오기
funcB = cls.getMethod("funcB", int.class);
//매개변수가 1개 있는 함수 불러오기
retValue = funcB.invoke(obj, 10);
System.out.println(methodFuncB + "() 결과 -> " + retValue);
//obj.funcA();
// obj.funcB();
System.out.println(obj);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
패키지의 타입 정보 얻기
package ch12.sec11.exam01;
getPackage() - 패키지 정보 읽기 //package ch12.sec11.exam01;
getSimpleName() - 패키지를 제외한 타입이름 //클래스 이름 출력 // Car
getName() - 패키지를 포함한 전체 타입이름 //클래스 이름을 포함한// ch12.sec11.exam01.Car
멤버 정보 얻기
getDeclaredConstructors() - 생성자 정보 읽기 // Constructor[] 로 반환
getDeclaredFields() - 필드 정보 읽기 // Field[] 로 반환
getDeclaredMethods() - 메소드 정보 읽기 // Method[] 로 반환
리소스 경로 얻기
class객체는 클래스 파일의 경로 정보를 가지고 있어서 이를 기준으로 다른 리소스 파일의 상대경로를 반환한다.
getResource(String) - 리소스 파일의 url리턴
getResourceAsStream(String) - 리소스 파일의 InputStream리턴
InputStream in = clazz.getResourceAsStream("photo1.jpg");
OutputStream out = new FileOutputStream("c:\\temp\\photo1.jpg");
in.transferTo(out);
in.close();
out.close();
어노테이션
컴파일할때나 실행할때 어떻게 처리해야 할 것인지 알려주는 설정정보
사용하는 경우
1. 정보전달
2. 컴파일 후 코드를 자동생성한다.
3. 컴파일 시 구문 오류 전달한다.
사용자 정의 어노테이션
@Target({ElementType.TYPE,ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationName{
String value() default "-";
int prop2() default 1;
}
@Retention
source 컴파일할때
class 메모리 로딩할때
runtime 실행시
어노테이션을 이용해서 매개변수 넘기기
@AnnotationName(value="-", number=15)
제네릭
클래스를 통해 객체를 만들때 타입도 매개변수로 넘겨받아 동적인 코딩이 가능하도록 한다.
아래와 같은 식으로 사용한다.
public class Box <T>{
public T content;
}
객체를 생성할때 T자리에 기본타입이 들어갈수 없다.
Box<String> box = new Box<String>();
<>안에 아무것도 안쓰면 Object타입이 암묵적으로 사용된다.
파라미터의 타입을 제한하고 싶을때 super와 extends를 사용할 수 있다.
super는 뒤에 나오는 클래스의 부모 클래스들을 전부 사용할 수있다.
extends는 뒤에 나오는 클래스의 자식클래스들을 전부 사용할 수 있다.
extends Number를 하면 숫자형자식객체들만 사용할 수 있다.
?은 범위에 있는 모든 타입으로 대체 할 수 있다.
public <T extends Number> boolean compare(T t1, T t2){
}
public static void registorCourse3(Applicant<? super Worker> applicant){
}
Course.registerCourse3(new Applicant<Person>(new Person()));
멀티 스레드
두개의 코드 실행흐름이다.
스레드 종료는 exit(), return으로한다.
메인스레드
메인스레드가 작업 스레드보다 먼저 종료되더라도 작업 스레드가 계속 실행중이라면 프로세스는 종료되지 않는다.
작업 스레드
몇개의 작업을 병렬로 실행할지 결정하고 각 작업별로 스레드를 생성해야 한다.
스레드는 Runnable인터페이스를 상속받아 run()을 오버라이딩해서 사용한다.
'JAVA공부(이것이 자바다)' 카테고리의 다른 글
컬렉션 자료구조 (0) | 2023.06.12 |
---|---|
스레드 (3) | 2023.06.09 |
java.base 모듈 (2) | 2023.06.07 |
중첩클래스 이어서 (0) | 2023.06.05 |
인터페이스 이어서 (0) | 2023.06.02 |