JAVA/JAVA Basic

[ JAVA ] 객체의 생성과 호출

IT록흐 2021. 6. 18. 20:17
반응형

 

 

 

객체 생성 연산자 : new

객체 접근 연산자 : . (도트)

 

 

이 두 가지만 알아도

객체의 많은 부분을 알 수 있다 생각한다.

 


 

new

 

객체는 Heap 영역에 생성된다.

 

Heap 영역에 객체생성을 지시하는

연산자가 new이다.

 

 

Studuent [참조타입] std [참조변수] = new Student() [생성자];

 

 

참조변수는 참조타입에 맞는 객체의 주소를 저장하는 변수다. new 연산자는 참조타입에 맞는 클래스의 생성자를 토대로 Heap 영역에 객체를 생성한다. 그리고 해당 객체의 주소를 return하여 = 연산자를 통해 참조변수에 저장한다.

 

생성자

 

생성자는 일반적으로 매개변수를 받아 객체의 필드값을 초기화하는데 사용된다. 생성자는 리턴타입이 없고 클래스의 이름과 동일하게 설정된다. 생성자는 굳이 코드로 작성하지 않아도 바이트 코드로 전환시 알아서 컴파일러가 기본 생성자를 추가한다.

 

그렇지만 매개변수를 받아야 한다면 직접 소스 코드로 작성해야한다. 매개변수를 얼마나 다양하게 받느냐에 따라 여러가지 생성자가 필요하다. 이를 위해 '생성자 오버로딩'을 한다.

 

public class Car{
  Car(){...}
  Car(String model){...}
  Car(String model, String color){...}
  Car(String model, String color, int maxSpeed){...}
}

 

 

개발자는 new 뒤에 원하는 형태의 생성자를 골라 사용하면 된다.

 

하지만 보시다시피, 생성자의 매개변수가 대부분 비슷함을 알 수 있다. 기존의 것에서 몇 개 추가되는 정도이다. 그러므로 {...} 안에 똑같은 코드들이 중복되어 사용된다. 이 문제를 해결하기 위해서 this 를 사용한다.

 

this란 객체 자기 자신을 의미한다. 우리는 자기 자신을 '나'라고 부른다. 객체는 자기 자신을 this라고 부른다.

 

public class Car {

	String company = "현대자동차";
	String model;
	String color;
	int maxSpeed;
	
	Car(){}
	
	Car(String model){
		this(model,"은색",250	);
	}
	

	Car(String model, String color){
		this(model,color,250);
	}

	Car(String model,String color, int maxSpeed){
	
		this.model = model;
		this.color = color;
		this.maxSpeed = maxSpeed;
	}
	
}

 

 

 

매개변수가 가장 많은 생성자를 토대로 this를 사용하면 중복코드를 많이 줄일 수 있다.

 


 

. 도트

 

 

new와 생성자를 통해 객체를 생성하고 초기화까지 완료했다면 이제는 객체를 사용해야한다. JAVA는 객체지향언어다. 객체들간의 소통으로 알고리즘이 구성된다. 그럼 객체들은 무엇을 이용하여 소통할까?

 

'메소드' 그리고 '리턴값'

 

메소드를 갖고 질문하면

리턴값으로 대답한다.

 

메소드

 

에어컨을 사용하려면 에어컨 전원 버튼만 누르면 되지, 에어컨의 동작회로를 조작할 필요는 없다. 에어컨은 '전원을 누르는 행위' 만을 사용자에게 공개하고 동작 회로는 에어컨 안 쪽으로 숨겨 놓는다.

 

이처럼 객체는 자신의 모든 정보를 공개하지 않는다. 숨길 정보(private)는 숨기고 공개할 정보(public)만 공개한다. 우리가 객체에 접근하려면 객체 자체가 아닌 객체가 공개한 메소드를 통해 접근해야한다.

 

이때 메소드에 접근하는 연산자가 . 도트 연산자이다.

Airconditioner AC = new Airconditioner(); // 먼저 객체를 생성하고 AC.turnOn; // . 연산자로 메소드를 '호출'한다.

 

 

 

호출

 

우리는 메소드를 '호출'한다는 표현을 쓴다.

 

 

'호출'이라는 표현을

쓰는 이유는 무엇일까?

 

 

남북한이 대화를 위해 판문점에서 만나듯, 많은 객체들은 대화를 위해 main 스레드에서 만난다. 남북한의 '외교관'들이 판문점으로 불리어져 회담을 하는 것과 같이, 객체의 'public 메소드'들은 main 스레드에 '호출'되어 대화를 진행한다.

 

그래서 클래스는 두 가지 종류가 있다. 실행 클래스 그리고 라이브러리 클래스. 총 100개의 클래스가 있다고 한다면 99개가 라이브러리 클래스이고 1개가 실행클래스(Main 클래스)이다.

 

 

 

객체의 메소드는 Heap영역에 저장되지 않는다. Heap 영역에는 객체의 필드값이 저장된다. 스레드에서 메소드를 '. 도트 연산자'를 통해 호출하면 스레드 안에는 '프레임(frame)'이 형성된다.

 

프레임은 스레드 안에 스택 방식으로 적재된다. 그래서 스레드가 저장되는 메모리 영역을 STACK 영역이라 부른다. 적재되는 프레임들은 LIFO (Last In First Out) 방식으로 PUSH(생성) 와 POP(제거)이 이루어진다.

 

 

 

main 메소드에서 cal객체의 avg 메소드를 호출하면 메인 스레드에 avg 프레임이 적재된다.

 

avg 메소드가 프레임으로 적재되면 메소드의 코드를 실행하는데 그 안에 plus 메소드 호출이 존재한다. 그러면 메소드 영역에서 plus 메소드를 읽어와 avg 메소드 위에 적재시킨다.

 

 

plus 메소드를 읽어 메인 스레드에서 프레임을 실행시켜 결과값을 return한다. 결과 값을 리턴하면 plus 메소드의 프레임은 스레드 Stack에서 POP되어 사라지고 다시 그 밑에 있는 avg 메소드 프레임을 실행시킨다. return값을 sum변수에 저장시키고 연산하여 return 시킨다. 그러면 avg 메소드 프레임도 POP되어 스레드에서 제거된다.

 

결과값을 받은 main 스레드는 System.out.println()으로 결과값을 출력시키고 스레드를 종료시킨다. 이것이 메모리 영역에서 일어나는 객체의 생성과 호출의 대략적인 과정이다.

 

 


 

정리

 

 

1. new와 생성자를 통해 Heap 영역에 객체를 생성한다.

2. main 스레드에서 .연산자를 통한 메소드 호출로 Stack에 프레임을 구성한다.

 

 

 

 

 

 

 

 

 

 

 

반응형