JAVA

[Java] 객체지향 (JVM구조, 오버로딩, 생성자, this.)

eehdev 2023. 1. 13. 01:41

     JVM의 메모리구조     

메서드 영역(method area)

  • 프로그램 실행 중에 어떤 클래스가 사용되면 해당 클래스에 대한 정보(클래스데이터)를 저장.
  • 이 때 그 클래스의 클래스 변수도 함께 생성

힙 영역(heap)

  • 인스턴스가 생성되는 공간. 인스턴스 변수들도 생성.

호출 스택(call stack)

  • 메서드 작업에 필요한 메모리가 제공되는 공간.
  • 메서드가 호출되면 호출스택에 메모리를 할당하고, 종료되면 해제한다.
  • 맨 위의 메서드 하나만 실행되고, 나머지는 대기한다.

 


     오버로딩     

  • 보통 하나의 메서드 이름에 하나의 메서드를 싣는데 오버로딩은 한 클래스 안에 같은 이름의 메서드를 여러개 정의하는 것.
  • 대표적인 예로 prinln() 메서드가 있다.
  • 오버로딩의 조건
    • 메서드 이름이 같을 것.
    • 매개변수의 개수, 타입, 또는 순서 중 하나가 달라야 한다. (반환타입은 영향❌)
      컴파일러는 매개값 타입을 가지고 메서드를 찾기 때문에 매개변수가 동일하다면 오버로딩❌
      메서드의 이름과 매개변수가 같고 반환타입만 다르다면 오버로딩❌
class MethodOverloading{
	public int add(int x , int y) {
		return x + y;
	}
	public int add(int x , int y, int z) {
		return x + y + z;
	} 
	public double add(double dx , int y) {
		return dx + y;
	}
	public double add(int x, double dx) {
		return x + dx;
	}
	public double add(double dx, double dy) {
		return dx + dy;
	}
}
public class MethodOverloadingExam {
	public static void main(String[] args) {
	
	MethodOverloading mo = new MethodOverloading();

	System.out.println("int x + int y : "+mo.add(10, 15));
	System.out.println("int x + int y + int z : " +mo.add(10, 15, 7));
	System.out.println("double dx + int y : " + mo.add(13.5, 15));
	}
}

🤔 코드 순서가 println 메서드가 먼저 와도 출력 순서는 add메서드가 먼저 출력된다. 왜일까?

→ println메서드가 결과를 출력하기 위해선 add메서드가 먼저 계산되어야 하기 때문이다!

🤔 add(int x , int y)줄이 없다고 할 때 add(10, 15)를 호출하면 < The method add(double, int) is ambiguous for the type ~ >에러가 뜸 왜일까?

→ add(double dx , int y)를 호출한 건지 add(int x, double dx)를 호출한 건지 알 수가 없기 때문

 


 

     생성자     

  • 인스턴스가 생성될 떄마다 호출되는 ‘인스턴스 초기화 메서드
    • 인스턴스 생성시 수행할 작업(초기화)에 사용
  • 메서드와 같이 클래스 내에 선언되지만 생성자는 리턴값이 없다.(void❌)
  • 생성자를 실행시키지 않고는 클래스로부터 객체를 만들 수 없다.
  • 모든 클래스는 생성자가 반드시 존재해야 하고, 하나 이상 가질 수 있다.
    • 생성자가 없으면 컴파일러가 기본 생성자를 자동으로 추가한다. 생성자가 1개라도 있으면 자동 추가
//기본생성자(매개변수가 없는 생성자)
클래스명(){}

//생성자 선언(매개변수가 있는 생성자)
클래스명(매개변수 선언, ...){     //매개변수는 new연산자로 생성자를 호출할 때 외부의 값을
		인스턴스 초기화 코드 작성     //생성자 블록 내부로 전달하는 역할
}

  • 매개변수가 다른 생성자를 여러개 선언하는 것.

2. 생성자 this()

  • 생성자에서 같은 클래스 안의 다른 생성자를 호출할 때 사용한다.
  • 다른 생성자 호출할 땐 반드시 생성자의 첫 줄에서만 사용
  • 오버로딩이 많아지면 생성자 간의 중복 코드가 발생할 수 있다
    • 따라서 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고
      나머지 생성자는 초기화 내용을 가진 생성자를 호출하는 것이다.(중복제거)
public class Car {
	String company, color;
	int speed;
	
	Car(){
		//Car("기아", "노랑", 250);
		this("기아", "노랑", 250);	//this()로 다른 생성자 호출 
	}
	Car(String company){
		this(company, "블랙", 300);	//this()로 다른 생성자 호출
	}
	Car(String company, String color, int speed){    //호출되는 생성자
		this.company = company;
		this.color = color;
		this.speed = speed;
	}}

 

3. 참조변수 this (생성자 this와 관계❌)

  • 객체 자신을 가리키는 참조변수 → 객체 자신의 주소가 저장되어 있다.
  • 인스턴스 메서드와 생성자에서 사용가능하다. → 지역변수로 숨겨진 채로 존재한다? 선언 안해도 사용가능
  • static 메서드에서 사용불가
  • 주로 지역변수(lv)와 인스턴스변수(iv)를 구별할 때 사용한다.
    (생성자와 메서드의 매개변수 이름이 필드와 동일한 경우)

💡 this.company등 this가 없으면 모두 lv로 간주한다.(가까운쪽) 따라서 this.가 있어야 iv로 간주함( 참조변수 .변수이름)