본문 바로가기
java

[Java] 표준 API #2 - System, Class + java.lang.reflect

by jinbro 2017. 10. 1.

[System]

1) java.lang.System

- jvm 위에서 실행되기때문에 운영체제의 모든 기능을 이용할 없지만 System으로 운영체제 일부 기능을 사용할 있음


(1) exit

(2) gc - java.lang.Object.finalize

(3) currentTimeMillis / nanoTime

(4) getProperty / getProperties

package com.jinbro.source.stdapi.system;


public class SystemTest {
public static void main(String[] args) {

/* exit : 프로세스 종료, 0은 정상종료 0이외의 값 비정상종료
System.exit(0); */

/* setSecurityManager : exit()가 실행되면 SecurityManager checkExit 메서드 자동호출 - 특정값에 대한 처리 가능 */
System.setSecurityManager(new SecurityManager(){
@Override
public void checkExit(int status) {
if(status == 5){
throw new SecurityException();
}
}
});

try{
System.exit(5); //이전에는 어떤 값을 넣어도 종료되었지만 지금은 익셉션 발생(처리하면 종료되지않음)
} catch(SecurityException e){
System.out.println(e.getMessage());
}


/* gc
1) 가비지컬렉터 처리 요청 : 바로 실행하지않음
2) 힙영역 객체 주소값이 스택영역 변수에 저장되어있지않으면 jvm은 메모리 부족, cpu 한가할 때 할당한 메모리 회수해감
3) 쓰레기 생길 때마다 처리 요청한다면 오히려 메모리 낭비(메모리 열악한 환경에서 사용) */
Member m1 = new Member(1);
m1 = null;
System.gc(); // 메모리 해제 전 Member.finalize() 실행 : 언제 처리될지 모름


/* currentTimeMillis : 시스템 시간을 1/1000초로 리턴, 주로 실행시간을 측정하기위해서 사용(현재 - 이전) */
long before = 0;
for(int i=0; i<3; i++){
if(i == 0){
before = System.currentTimeMillis();
continue;
}

long gap = System.currentTimeMillis() - before;
System.out.println(gap);
}

/* nanoTime : 시스템 시간을 1/109초로 리턴, 주로 실행시간을 측정하기위해서 사용(현재 - 이전) */
long time1 = System.nanoTime();

int cnt = 0;
for(int i=0; i<300; i++){
cnt += i;
}

long time2 = System.nanoTime();
System.out.println(time2 - time1 + "나노초 소요됨");


/* getProperty(key)
1) 운영체제, jvm 시스템 속성값을 얻어올 수 있음 : 클라이언트 시스템 속성에따라 분기처리(?)
2) key(파라미터) - value(리턴값) 구성
3) 일부 key는 permission denied에 의한 예외 발생
4) System.getProperties() : HashTable<T, T> 타입, key - value 객체 리턴*/
System.out.println(System.getProperty("java.version"));
System.out.println(System.getProperty("os.name"));


/* getenv(key)
1) 운영체제에서 제공하는 환경변수(value)를 읽어옴(프로그램에 제공 목적)
2) 내부적으로 SecurityManager로 퍼미션 체크함

getenv()
1) 환경변수(key-value) 목록 */
try {
//access denied, 퍼미션 어떻게 주는지도
System.out.println(System.getenv());
System.out.println(System.getenv("JAVA_HOME"));
} catch(Exception e){
System.out.println(e.getMessage());
}

}
}

class Member{

private int num;

public Member(int num){
this.num = num;
}

@Override
protected void finalize() throws Throwable {
System.out.println(this.num +"이 가비지컬렉터에 의해 제거되었습니다");
}
}



[Class + Reflection]

2) java.lang.Class

- 로드된 클래스, 인터페이스 정보(클래스 풀네임, 메서드, 필드 ) Class 관리함

- java.lang.reflect : 로드된 클래스에 대한 처리(java.lang.Class 함께)

=> 클래스 정보를 찾아와서 담을 있는 객체타입 제공


(1) getClass / forName

(2) getDeclaredMethods - Fields - Constructors

(3) newInstance

package com.jinbro.source.stdapi.classclass;

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

public class ClassTest{

private String name;

public ClassTest(String name){
this.name = name;
}

public static void main(String[] args) {

/*** 리플렉션 : 로드되어있는 클래스의 정보를 얻음 ***/
/* getClass() : 인스턴스 생성했을 때 사용가능 */
ClassTest t1 = new ClassTest("jinbro");
Class clazz = t1.getClass();

System.out.println(clazz.getName());

/* forName() : 인스턴스 생성하지않고도 로드되어있는 클래스를 가져올 수 있음 */
try{
clazz = Class.forName("com.jinbro.source.stdapi.classclass.ClassTest");
Method[] methods1 = clazz.getMethods(); //public까지만 가져옴

for(Method m : methods1){
System.out.println("메서드 목록(Object 포함) : "+m.getName());
}

Constructor[] constructors = clazz.getConstructors();
System.out.println(constructors.length); // or for문 c.getParameterCount()

/* getDeclaredConstructors, getDeclaredFields, getDeclaredMethods
- 상속을 제외한 클래스에 선언된 생성자, 필드, 메서드만 가져옴 : 기본적으로 상속관계를 가지는 Object로 테스트
*/
Method[] methods2 = clazz.getDeclaredMethods();
for(Method m : methods2){
System.out.println("메서드 목록(Object 미포함) : "+m.getName());
}


} catch(ClassNotFoundException e){
System.out.println("해당 클래스는 로드되어있지않습니다");
}
/****************************************/

/* newInstance
1) 동적으로 객체 생성, 런타임에 임의클래스 인스턴스 생성
2) 기본 생성자를 호출하게되어있음 : 기본생성자를 만들어야함 */


try{
/* Object 타입이므로 강제형변환하거나 공통된 필드 - 메서드만 사용
1) 완전 모르는 경우가 아니라 하나의 인터페이스를 구현하고 있는 두개 이상의 클래스 중 1개의 인스턴스를 생성할 때
=> 인터페이스 타입으로 강제형변환 후 메서드 호출하면 둘 중 생성된 인스턴스의 오버라이딩 메서드가 호출됨 */
Class clazz1 = Class.forName("com.jinbro.source.stdapi.classclass.Member");
Score s = (Score)clazz1.newInstance();
s.setScore(100);
System.out.println(s.getScore());


/* 기본 생성자 없이 newInstance로 동적 객체 생성
Constructor[] constructors = clazz1.getConstructors();
for(Constructor constructor : constructors){

} */
}catch(ClassNotFoundException e){
System.out.println("로드된 클래스 아님");
}catch(IllegalAccessException e){
System.out.println("접근제어자에 의해 예외발생");
}catch(InstantiationException e){
System.out.println("추상클래스, 인터페이스, 기본 생성자없는 경우 예외 발생");
}


}
}

interface Score {
public void setScore(int num);
public int getScore();
}

class Member implements Score {
private int num;
private int score;

public Member() {
this(10);

}

public Member(int num){
this.num = num;
this.score = 0;
}

public int getNum() {
return num;
}

@Override
public String toString() {
return "Member{" +
"num=" + num +
'}';
}

@Override
public void setScore(int num) {
this.score += num;
}

@Override
public int getScore() {
return this.score;
}
}





댓글