Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

Super Coding Addict

Ch10. 자바 기본 클래스 (4) - Class 클래스 본문

JAVA 문법

Ch10. 자바 기본 클래스 (4) - Class 클래스

밍응애 2021. 3. 1. 15:28

* Class 클래스

- 자바의 모든 클래스와 인터페이스는 컴파일 후 class 파일로 생성된다

- class파일에는 객체의 정보(멤버변수, 메서드, 생성자 등)가 포함되어 있다

- Class 클래스는 컴파일된 class파일에서 객체의 정보를 가져올 수 있다

 

- 동적 로딩할 때 많이 씀

- 로컬에 자료형(모듈)이 없는 경우에도 씀

 

* Class 클래스 가져오기

1.

String s = new String();
Class c = s.getClass();

--> getClass()메서드는 Object의 메서드

 

2.

Class c = String.Class;

 

3. 동적로딩 -- 런타임때 바인딩이 됨   cf. 정적로딩 -- 컴파일타임 때

=> 그때그때 내 필요에 맞게 원하는 라이브러리/클래스를 매칭시킬 수 있다는 장점

=> 오타가 나면 로딩되다가 ClassNotFoundException이 나서 런타임이 죽을 수 있음

Class c = Class.forName("java.lang.String");

--> ""안에 명시된 클래스가 로컬에 있으면 runtime때 불러다가 사용

=> 언제든 변수화해서 바꿀 수 있음

가령, 자바에서 JDBC를 쓸 때 여러 DB라이브러리가 있을 수 있는데 그런 라이브러리들을 모두 static하게 링크해서 컴파일할 순 없으므로 (너무 많아서) 라이브러리들은 install해놓 고 필요할 때 부를 수 있게 끔 함

ex) 오라클 라이브러리의 이름을 넣으면 동적로딩 됨!

 

- 예제 1) Class클래스 가져오기

package ch10.classEx;

public class StringClassTest {

	public static void main(String[] args) throws ClassNotFoundException {
		Class c1 = String.class;
		
		String str = new String();
		Class c2 = str.getClass();
		
		Class c3 = Class.forName("java.lang.String");

	}

}

 

* reflection 프로그래밍

- Class 클래스로부터 객체의 정보를 가져와 프로그래밍하는 방식

- 로컬에 객체가 없고 자료형을 알 수 없는 경우 유용한 프로그래밍

- java.lang.reflect 패키지에 있는 클래스 활용

 

- 예제 2) reflection 패키지 활용

package ch10.classEx;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class StringClassTest {

	public static void main(String[] args) throws ClassNotFoundException {
		
		Class c3 = Class.forName("java.lang.String");
		
		Constructor[] cons = c3.getConstructors();
		for(Constructor con : cons) {
			System.out.println(con);
		}
		
		System.out.println();
		
		Method[] methods = c3.getMethods();
		for(Method method : methods) {
			System.out.println(method);
		}
	}

}

--> java.lang.reflect패키지에 있는 Constructor클래스와 Method클래스를 활용하여 String클래스가 가지고 있는 Constructor와 Method 확인 가능

 

* forName() 메서드와 동적 로딩

- Class클래스의 static메서드

- 동적 로딩이란?

: 실행 중(런타임)에 데이터 타입을 알고 binding되는 방식

cf. 정적 로딩 : 컴파일 시 데이터 타입이 모두 binding되어 자료형이 로딩되는 것

- 실행 시에 로딩되므로 경우에 따라 다른 클래스가 사용될 수 있어 유용하다

- 컴파일 타임에 체크할 수 없으므로, 해당 문자열에 대한 클래스가 없는 경우 예외(ClassNotFoundException) 발생 가능

 

- 예제 : Person 클래스 동적로딩

 

# Perosn 클래스

package ch10.classEx;

public class Person {
	
	private String name;
	private int age;
	
	public Person() {};
	
	public Person(String name) {
		this.name = name;
	}
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public String toString() {
		return name;
	}
	
	
}

--> 생성자가 기본생성자를 포함해 3가지가 있는 클래스

 

# ClassTest 클래스

package ch10.classEx;

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

public class ClassTest {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		Person person = new Person("James");
		System.out.println(person);
		
		Class c1 = Class.forName("ch10.classEx.Person");
		Person p1 = (Person)c1.newInstance(); //Default Constructor를 호출
		System.out.println(p1);
		
		Class[] parameterTypes = {String.class};
		Constructor cons = c1.getConstructor(parameterTypes);
		
		Object[] initargs = {"김유신"};
		Person personLee = (Person)cons.newInstance(initargs);
		System.out.println(personLee);

	}

}

Class c1 = Class.forName("ch10.classEx.Person");

--> Class.forName("ch10.classEx.Person");으로 Person클래스를 동적 로딩

 

 

Person p1 = (Person)c1.newInstance(); //Default Constructor를 호출
System.out.println(p1);	//결과 : null

--> 가져온 Class로 newInstance()를 하면 기본생성자가 호출되므로 p1을 toString()으로 찍어보면 null이 찍힌다 (아무런 매개변수가 들어가지 않았으므로)

--> newInstance()가 반환하는 객체의 타입이 Object이므로 (Person)으로 다운캐스팅

 

 

Class[] parameterTypes = {String.class};
Constructor cons = c1.getConstructor(parameterTypes);
		
Object[] initargs = {"김유신"};
Person personLee = (Person)cons.newInstance(initargs);
System.out.println(personLee); //결과 : 김유신

--> 가져온 Class에서 String클래스의 인자를 파라미터값으로 갖는 생성자를 가져와 cons 변수에 넣음

--> 생성자의 인자로 들어갈 String클래스 변수로 "김유신"을 initargs 변수에 넣음

=> 만약 String클래스의 인자가 여러 개 필요하다면 이 Object배열에 "김유신"뿐만 아니라, 필요한 인자를 더 넣어준다

--> 마찬가지로 newInstnace()가 반환하는 객체 타입이 Object이므로 (Person)으로 다운캐스팅한다

 

 

==> 로컬에 있는 클래스라면 쉽게 생성자를 호출할 수 있지만, 로컬에 없는 클래스인 경우 이런식으로 생성자나 메서드를 호출할 수 있기에 쓴다