-
Java - 기본 클래스(Class 클래스)5개발언어/JAVA 2023. 11. 6. 16:46
Class 클래스
자바의 모든 클래스와 인터페이스는 컴파일되고 나면 class 파일로 생성된다. 예를 들어 a.java 파일이 컴파일 되면 a.class 파일이 생성되고 이 class파일에는 클래스나 인터페이스에 대한 변수, 메서드, 생성자 등의 정보가 들어있다. Class 클래스는 컴파일된 class 파일에 저장된 클래스나 인터페이스 정보를 가져오는데 사용한다.
Class 클래스란?
앞 전 까지의 Java 문법에 대한 게시물에 예시 코드에서는 변수를 선언할 때 자료형을 미리 파악하고 그 자료형에 따라 변수를 선언했다. 그리고 클래스를 사용할 대도 이미 그 클래스 정보(변수,매서드 등)를 알고 있는 상황에서 프로그램을 만들었다.
그런데 코드를 짜다 보면 어떤 경우에는 여러 클래스 주에 상황에 따라 다른 클래스를 사용해야 할 때도 있고, 반환받는 클래스가 정확히 어떤 자료형인지 모를 때도 있다. 이렇게 모르는 클래스의 정보를 사용할 경우에 클래스 정보를 직접 찾아서 사용해야 한다. 이때 Class 클래스를 활용한다.
클래스 정보를 가져오는 방법 3가지
1. Object 클래스의 getClass()메서드 사용하기
String s = new String(); Class c = s.getClass(); //getClass()메서드의 반환형은 Class
Object의 멤버 메서드인 getClass()메서드는 모든 클래스가 사용할 수 있는 메서드 이다. 이 매서드를 사용하려면 이미 생성된 인스턴스가 있어야 한다.
2. 클래스 파일 이름을 Class 변수에 직접 대입하기
Class c = String.Class;
3. Class.forName("클래스 이름")메서드 사용하기
Class c = Class.forName("java.lang.String");
2,3 번의 경우 컴파일된 클래스 파일이 있아면 클래스 이름만으로 Class 클래스를 반환받는다.
Class 클래스 가져오는 예시코드
person.java
package 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; } }
classTest.java
package classex; public class ClassTest { public static void main(String[] args) throws ClassNotFoundException { Person person = new Person(); //1.Object의 getClass()메서드 사용하기 Class pClass1 = person.getClass(); System.out.println(pClass1.getName()); //classex.Person //2.직접 class 파일 대입하기 Class pClass2 = Person.class; System.out.println(pClass2.getName()); //classex.Person //3.클래스 이름으로 가져오기 Class pClass3 = Class.forName("classex.Person"); System.out.println(pClass3.getName()); //classex.Person } }
Class 클래스를 활용해 클래스 정보 알아보기
프로그래밍을 하다 보면 내가 사용할 클래스의 자료형을 모르는 경우가 있을 수 있다. 예를 들어 로컬 컴퓨터에 저장되어 있지 않은 객체를 메모리에 로드하고 생성하는 경우 그 객체에 정보를 알 수 없다. 이때 Class 클래스를 가져올 수 있다면 해당 클래스의 정보, 즉 생성자·메서드·멤버 변수 정보를 찾을 수 있다. 이렇게 사용하려는 클래스의 자료형을 모르는 상태에서 Class 클래스를 활용하여 그 클래스의 정보를 가져오고, 이 정보를 활용하여 인스턴스를 생성하거나 메서드를 호출하는 방식을 '리플렉션(reflection)'이라고 한다.
package stirng; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class StringClassTest { public static void main(String[] args) throws ClassNotFoundException{ //클래스 이름으로 가져오기 Class strClass = Class.forName("java.lang.String"); //모든 생성자 가져오기 Constructor[] cons = strClass.getConstructors(); for(Constructor c :cons){ System.out.println(c); } //모든 멤버 변수(필드) 가져오기 Field[] fields = strClass.getFields(); for(Field f : fields){ System.out.println(f); } //모든 메서드 가져오기 Method [] methods = strClass.getMethods(); for(Method m : methods){ System.out.println(m); } } }
newInstance()를 사용해 클래스 생성하기
package classex; import classex.Person; public class NewInstanceTest { public static void main(String[] args)throws ClassNotFoundException, InstantiationException, IllegalAccessException{ //생성자로 생성하기 Person person1 = new Person(); System.out.println(person1); //classex.Person@6a5fc7f7 //Class 클래스로 newInstance()메서드로 생성하기 Class pClass = Class.forName("classex.Person"); Person person2 = (Person)pClass.newInstance(); System.out.println(person2); //classex.Person@3b6eb2ec } }
클래스의 생성자를 사용하지 않아도 Class 클래스의 메서드 중 하나인 newInstance()메서드를 사용해서 인스턴스를 생성할 수도 있다. 주의할 점은 newInatance()메서드는 항상 Object 타입을 반환하므로 생성된 객체형으로 형변환 하는 코드를 추가 해주어야 한다.
Class 클래스를 사용하는 방법은 클래스의 자료형을 사용하여 프로그래밍하는 것보다 더 복잡하고, 예외처리도 해야한다. 이미 자료형을 알고 있는 클래스인 경우 또는 컴파일할 때 직접 참조할 수 있는 클래스는 Class 클래스를 활용할 필요가 없다. 클래스의 정보를 모두 알고 있는 상황에서 리플렉션 프로그래밍을 하면 오히려 코드가 복잡해지고 속도도 느려진다. 따라서 리플렉션 프로그래임은 컴파일 시점에 알 수 없는 클래스, 즉 프로그램 실행 중에 클래스를 메모리에 로딩하거나 객체가 다른 곳에 위치해서 원격으로 로딩하고 생성할 때 사용한다.
Class.forName()을 사용해 동적 로딩하기
대부분의 클래스 정보는 프로그램이 로딩될 때 이미 메모리에 있다. 그런데 이런 경우를 생각해보자. 어떤 회사에서 개발한 시스템이 있는데, 그 시스템은 여러 종류의 데이터베이스를 지원한다. 오라클, MySQL, MS-SQL 등등 여러 데이터베이스를 연동할 수 있다. 그렇다고 이 시스템을 컴파일할 때 모든 데이터베이스 라이브러리(드라이버)를 같이 컴파일할 필요는 없다. 시스템을 구동할 때 어떤 데이터베이스와 연결할지 결정된다면 해당 드러이버만 로딩하면 된다. 회사가 사용하는 데이터베이스 정보는 환경 파일에서 읽어 올 수도 있고 다른 변수 값으로 받을 수도 있다. 즉 프로그램 실행 이후 클래스의 로딩이 필요한 경우 클래스의 '동적 로딩(dynamic loading)' 방식을 사용한다. 자바는 Class.forName()메서드를 동적 로딩으로 제공한다.
Class pClass = Class.forName("classex.Person");
forName()메서드를 잘 살펴보면 매개변수로 문자열을 입력받는다. 이때 입력받는 문자열을 변수로 선언하여 변수 값만 바꾸면 다른 클래스를 로딩할 수 있다. 앞에서 설명했듯이 여러 데이터베이스 드라이버 중 필요한 드라이버의 값을 설정 파일에서 읽어 문자열 변수로 저장한다면, 설정 파일을 변경하므로써 필요한 드라이버를 간단하게 로딩할 수 있다.
String className = "classex.Person" Class pClass = Class.forName(className);
[출저 - Do it! 자바 프로그래밍 입문 , 박은종]
http://www.easyspub.co.kr/20_Menu/BookView/A001/267/PUB
'개발언어 > JAVA' 카테고리의 다른 글
JAVA 람다와 스트림 - 람다식(Lambda Expression) (1) 2023.12.15 Java - 컬렉션 프레임워크(제네릭)1-1 (0) 2023.11.07 Java - 기본 클래스(Wrapper 클래스)5 (0) 2023.11.06 Java - 기본 클래스(String 클래스)4 (0) 2023.11.06 Java - 기본 클래스(Objectd의 equals()메서드)2 (0) 2023.11.04