본문 바로가기

JAVA/JAVA 기초

객체의 라이프 사이클

반응형

객체의 라이프 사이클

자바의 객체의 생존 기간을 라이프 사이클이라고 한다.

객체가 생성된 후부터 폐기될 때 까지의 기간을 뜻한다.


1) 로컬변수

로컬변수는 처리 블록 내에서만 사용할 수 있는 변수

변수를 선언한 곳에서 생성되어 블록이 종료한 시점에서 폐기된다.


2)인스턴스 변수

클래스의 필드로 선언하는 변수


부모 객체를 생성할 때 생성되어 부모 객체가 가비지 컬렉션될 때 함께 삭제된다.


3)클래스 변수

클래스의 static 필드로 선언한 변수

자바의 변수 중 가장 긴 라이프 사이클

클래스 로드시에 생성되어 클래스가 언로드되면 소멸된다.

대부분의 경우 자바의 프로세스 시작시에 생성되어 프로세스 종료시 삭제된다.

또한, 인스턴스 변수와 클래스변수에는 가시성을 지정할 수 있다.



public class LifeCycleSample {

//클래스 변수

public static int classVariable = 1;

//인스턴스변수

public int instanceVariable = 1;

public void someMethod() {

//로컬변수

int localVariable = 1;

if(instanceVariable > 0 ) {

//로컬변수

int localSubVariable = 1;

} //localSubVariable 소멸

} //localVariable 소멸

}



1) 라이프 사이클을 짧게하여 사고를 방지

라이프 사이클이 길면 길수록 의도하지 않게 값이 변경될 가능성이 커진다.

인스턴스 변수를 사용하는 경우 로컬 변수로 대체할수 없는지 생각해본다.

'메서드의 인수에 전달할 변수가 많다', '인수를 쓰는것이 귀찮다'는 이유로 클래스에 인스턴스 변수를 선언하여 메서드 안에서 사용하는 코드는 피하는 것이 좋다.

특히 멀티 스레드하에서는 값을 설정한 후 목적의 처리를 실행하기 전에 의도하지 않은 값의 변경이 발생할 가능성이 있다.

'값은 메서드의 인수로 전달한다', '수가 많은 경우 클래스에 정리한다' 등 인스턴스 변수를 사용하지 않도록 한다.


public class EmployeeService {

private int id;

private String name;

private LocalDate birth;

public void create() {

//id, name, birth의 값을 파일에 보관한다.

}

public void get(int id) {

//지정된 id와 일치하는 데이터를 파일로부터 읽어들인다.

//id, name, birth에 값을 설정한다.

}

}


public class MainService {

private EmployeeService employeeService = new EmployeeService();

public void register() {

this.employeeService.setId(1);

this.employeeService.setName("은유");

this.employeeService.setBirth(LocalDate.of(1990, 12, 2));

this.employeeService.create();

}

public void show(){

this.employeeService.get(1);

System.out.println(this.employeeService.getName());

System.out.println(this.employeeService.getBirth());

}

}

EmployeeService 인스턴스에 대해 id, name, birth 값을 설정한 후 create() 메서드를 호출해 파일에 저장하는 형태로 되어 있다.

값을 설정한 후에 파일로 저장할 때 까지 EmployeeService 인스턴스 값을 유지해야한다.

create() 호출하기 전에 즉시 다른 처리가 중간에 끼어들어 값의 갱신을 실행했다면 원래의 처리에서는 의도하지 않는 값이 파일에 기록되어 버그가 발생한다.


public class Employee {

public int id;

public String name;

public LocalDate birth;

}



public class EmployeeService {

public void create(Employee employee) {

//employee.id, eomployee.name, employee.birth의 값을 파일에 보관한다.

}

public Employee get(int id) {

//지정된 id와 일치하는 데이터를 파일로부터 읽어들여 반환

}

}



public class MainService {

private EmployeeService employeeService = new EmployeeService();

public void register() {

Employee employee = new Employee();

employee.id = 1

employee.name = "은유";

employee.birth = LocalDate.of(LocalDate.of(1990, 12, 2));

this.employeeService.create(employee);

}

public void show(){

Employee employee = this.employeeService.get(1);

System.out.println(employee.name);

System.out.println(employee.birth);

}

}


변경이 가능한 변수에 대해서는 클래스 변수를 사용하는 것보다 인스턴스 변수를 이용하도록 한다.

클래스 변수는 어떤 타이밍에서도 바꿔 쓰기가 가능하며, 특히 멀티 스레드에서의 동시 액세스에 의해 의도하지 않은 변경이 발생할 확률이 인스턴스 변수보다 높기 때문에 가능한 사용하지 않도록 한다.


2)라이프 사이클 길게하여 성능을 높이기

라이프 사이클을 길게하는 경우

라이프 사이클을 짧게하면 수명이 짧은 객체가 많이 만들어져 그만큼 가비지 컬렉션의 발생 횟수도 증가한다.

애플리케이션의 성능을 악화시키는 요인 중 하나이기도 하므로 횟수, 시간 모두를 줄이는 것이 성능에 좋다.

라이프 사이클을 길게하여 값을 재사용할 수 있기 때문에 GC의 양을 줄일수 있다.

그러나 라이프 사이클이 긴 객체가 너무 많아지면 오히려 GC가 늘어날수 있기 때문에 어떤 객체의 라이프 사이클을 늘리지 검토가 필요하다.

인스턴수 변수와 클래스 변수 등의 필드가 없는 클래스(상태가 없는 클래스(stateless class))는 여러 스레드에서의 액세스에 따른 사고의 걱정도 없기 때문에 적극적으로 라이프 사이클을 길게 하면 좋을 것이다.

참고로 모든 메서드는 static으로 하는 유틸리트 클래스를 작성하는 일이 자주 있다.

유틸리티 클래스의 메서드가 모두 static인 이유는 인스턴스 생성의 부담을 덜 수 있다는 데 있다.

유틸리티 클래스를 매번 new 메서드를 호출하는 것보다 직접 메서드를 호출하는 편이 효율적이기 때문이다.

단, static 메서드만으로는 확장성이 없고 테스트를 할때 메서드를 모의 객체로 만들 수 없기 때문에 유틸리티 클래스 자체는 nonstatic 메서드로 구성하고 그것의 인스턴스를 static으로 하는 방식으로 한다.


public class StringUtils {

//static 붙이지 않음

public boolean isEmpty(String text) {

return (text == null || text.length() == 0);

}

}


public class MainService {

//유틸리티 클래스의 인스턴스를 생성하여 static 취급한다.

private static StringUtils stringUtils  = new StringUitils();

public void execute(String text) {

//static 인스턴스의 메서드를 호출한다.

if(stringUtils.isEmpty(text)) {

}

}

}


출처: 자바 마스터북

반응형

'JAVA > JAVA 기초' 카테고리의 다른 글

자바 코딩 규약  (0) 2019.11.26
Object의 clone() 복사  (0) 2019.03.12
가시성  (0) 2018.10.25
값 전달 방법(callByValue callByReference)과 불변객체  (0) 2018.10.25
문자열관련  (0) 2018.10.22