[DEV] study&learn
article thumbnail
 너무 소심하고 까다롭게 자신의 행동을 고민하지 말라.
모든 인생은 실험이다.
더많이 실험할수록 더나아진다
– 랄프 왈도 에머슨

 

"6-3" 생성자

생성자(Constructor)는 new 연산자로 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당한다.

 

객체 초기화란 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는 것을 말한다.

생성자를 실행하지 않고는 클래스로부터 객체를 만들 수 없다. 

new 연산자에 의해 생성자가 성공적으로 실행되면 힙(heap) 영역에 객체가 생성되고 객체의 번지가 리턴된다.

리턴된 객체의 번지는 클래스 변수에 저장된다.

 

[출처] https://gallery-k.tistory.com/236

기본 생성자

모든 클래스는 생성자가 반드시 존재하며, 생성자를 하나 이상 가질 수 있다.

클래스 내부에 생성자 선언을 생략했다면 컴파일러는 중괄호 { } 블록 내용이 비어 있는 기본 생성자를 바이트 코드에 자동 추가한다.

이때문에 클래스에 생성자를 선언하지 않아도 new 연산자 뒤에 기본 생성자를 호출해 객체를 생성할 수 있는 것이다.

그러나 클래스에 명시적으로 선언한 생성자가 1개라도 있으면 컴파일러는 기본 생성자를 추가하지 않는다.

명시적으로 생성자를 선언하는 이유는 객체를 다양한 값으로 초기화하기 위함이다.

 

클래스가 public 으로 선언되면 기본 생성자에도 public이 붙는다.

 

생성자 선언

public class Car {
	Car ( String color, int speed ) { 
    	// 객체 초기화 코드가 들어갈 수 있다.
    }
}

위 코드에서 Car 생성자는 String 타입 변수 1개와 int 타입 변수 하나를 매개 변수로 받는다.

위 코드처럼 생성자가 명시되어 있는 경우, 기본 생성자가 자동 생성되지 않기 때문에,

Car mycar = new Car();

로 객체를 생성할 수 없다.

 

필드 초기화

클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정된다.

만약 다른 값으로 초기화하고 싶다면 두 가지 방법이 있다.

  1. 필드를 선언할 때 초기값을 주는 방법
  2. 생성자에서 초기값을 주는 방법
public class Korean {
	// 필드
    String nation = "대한민국";
    String name;
    String ssn;
    
    // 생성자
    public Korean(String name, String ssn) {
    	this.name = name;
        this.ssn = ssn;
    }
}

위 코드에서

nation 은 필드에서 초기값을 주었고,

name 과 ssn 은 생성자를 통해서 초기값을 주었다.

 

this 는 객체 자신의 참조이다.

우리가 우리 자신을 '나'라고 하듯이 객체가 자기 자신을 this 라고 한다.

this.필드는 this 라는 참조 변수로 필드를 사용하는 것과 동일하다.

(필드 이름과 매개 변수의 이름을 동일하게 사용하면 좋은데, this 를 통해 이를 가능하게 해준다.

이름을 같게 해주고 this 를 사용하지 않으면 필드에 접근할 수 없다.

왜냐하면 코드와 가까운 동일한 이름의 매개 변수의 사용 우선순위가 높기 때문이다.)

 

생성자 오버로딩

생성자 오버로딩이란 매개 변수를 달리하는 생성자를 여러 개 선언하는 것을 말한다.

 

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

 

생성자 오버로딩시 주의 사항

매개 변수의 타입, 그리고 그 선언 순서가 똑같을 경우 매개 변수의 이름만 바꾸는 것은 생성자 오버로딩이 아니다.

Car(String model, String color) { }
Car(String color, String model) { }
// 생성자 오버로딩이 아님

 

다른 생성자 호출: this()

this() 와 this 는 다른 것!!!

생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있다.

매개 변수의 수만 달리하고 필드 초기화 내용이 비슷한 생성자에서 자주 발생.

 

이 경우에는 필드 초기화 내용은 한 생성자에서만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있다.

 

this() 는 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫 줄에서만 허용된다.

이 말은 호출되는 생성자의 실행이 끝나면 원래 생성자로 돌아와 다음 실행문을 진행한다는 뜻이다.

 

"6-4" 메소드

  • 리턴 타입
  • 메소드 이름
  • 매개 변수 선언
  • 메소드 실행 블록

으로 구성되어 있다.

선언부(리턴 타입, 메소드 이름, 매개 변수 선언) + 실행 블록

 

리턴 타입

리턴값의 타입을 말한다.

리턴값이란 메소드를 실행한 후의 결과값을 의미.

 

리턴값이 '있느냐, 없느냐', '받을 것이냐, 받지 않을 것이냐'에 따라 호출하는 방법이 다르다.

(리턴 타입이 존재하더라도 리턴값을 받지 않고 메서드 실행만 할수 도 있다.)

// 리턴값이 없거나, 받지 않을 경우
powerOn();

// 리턴값이 있고, 받을 경우
double result = divide(10, 20);

 

메소드 이름

자바 식별자 규칙에 맞게 작성

  • 숫자로 시작하면 안되고, $와 _를 제외한 특수 문자를 사용하면 안된다.
  • 관례적으로 메소드 이름은 소문자로 작성한다.
  • 서로 다른 단어가 혼합된 이름이라면 뒤이어 오는 단어의 첫 글자는 대문자로 작성한다.

 

매개 변수 선언

매개 변수메소드가 실행될 때 필요한 데이터를 외부로부터 받기 위해 사용된다.

메소드에서 매개 변수가 필요한 경우도, 필요하지 않은 경우도 있다.

 

// 매개 변수 x
powerOn();

// 매개 변수 o
double result = divide(10, 20);

 

외부 클래스에서 어떤 클래스의 메소드를 호출하기 위해서는

사용할 클래스의 객체를 생성하고 참조 변수와 도트 연산자를 이용해 메소드에 접근하여 호출한다.

( new -> 참조변수.메서드이름 )

 

매개 변수의 개수를 모를 경우

아래와 같이 2가지 방법으로

메소드에 인자를 주고,

메소드는 매개 변수를 받을 수 있다.

// 1.
int sum(int[] values) { }

// 1-1.
int[] values = {1, 2, 3}
int result = sum(values);
// 1-2.
int result = sum(new int[] {1, 2, 3}


// 2.
int sum(int ... values) { }

// 2-1.
int result = sum(1, 2, 3);

 

리턴(return)문

1. 리턴값이 있는 메소드

리턴 타입이 있는 메소드는 반드시 리턴문을 사용해 리턴값을 지정해야 한다.

만약 return 문이 없다면 컴파일 에러가 발생하고,

return 문이 있다면 return 문 실행 후 메소드가 즉시 종료된다.

return 리턴값;

2. 리턴값이 없는 메소드: void

리턴값이 없는 메소드는 리턴 타입으로 void 를 가진다.

 

하지만 void 로 선언된 메소드에서도 return 문을 사용할 수 있다.

이것은 리턴값을 지정하는 것이 아니라 메소드 실행을 강제 종료시키는 역할을 한다.

뒤에 추가적으로 실행시켜야할 실행문이 있다면
return이 아닌 break문을 사용하여야 한다.

 

메소드 호출

메소드는 클래스 내/외부의 호출에 의해 실행된다.

 

  1. 클래스 내부의 다른 메소드에서 호출할 경우에는 단순히 메소드 이름으로 호출하면 되지만
  2. 클래스 외부에서 호출할 경우에는 우선 사용할 메소드가 담긴 클래스로부터 new 연산자를 통해 객체를 생성한 뒤,
    참조 변수와 도트(.) 연산자를 이용해서 메소드를 호출해야 한다. (객체가 존재해야 메소드도 존재)

 

메소드 오버로딩

클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것을 메소드 오버로딩(overloading)이라고 한다.

오버로딩의 사전적 의미는 많이 싣는 것을 뜻한다.

 

메소드 오버로딩의 조건은 매개 변수의 타입, 개수, 순서 중 하나가 달라야 한다는 점이다.

class Plus {
	int add(int i, int j) { }
    
    double add(double i, double j) { }
}

 

오버로딩된 메소드를 호출할 경우 JVM은 매개값의 타입을 보고 메소드를 선택한다.

(이 과정에서 자동 타입 변환이 가능한지도 검사한다.)

profile

[DEV] study&learn

@devjuni

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!