-
[자바의 정석] Chapter06-2. 객체지향프로그래밍1스터디플래너/공부하기 2022. 2. 14. 08:19
- 오버로딩(Overloading)
- 오버로딩이란
- 메서드도 변수처럼 같은 클래스 내에서 서로 다른 이름을 가져야 한다. 하지만 매개변수의 개수나 타입이 다르다면 한 클래스 내에서 이미 사용하는 메서드의 이름과 같은 이름으로 메서드를 정의할 수 있다. 이렇게 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것을 메서드 오버로딩(method overloading) 또는 오버로딩(overloading)이라 한다.
- 오버로딩의 조건
- 오버로딩이 성립하기 위해서는 1. 메서드의 이름이 같아야 하고, 2. 매개변수의 개수 또는 타입이 달라야 한다. 이 두가지 조건을 만족하지 못하면 중복 정의로 간주되어 컴파일할 때 에러가 발생한다. 오버로딩된 메서드는 매개변수에 의해 구분할 수 있으므로 반환타입이 다르더라도 메서드의 이름이 같고 매개변수의 개수와 타입이 같다면 에러가 발생한다.
- 오버로딩의 예
- 오버로딩의 장점
- 오버로딩이 없다면 같은 기능을 하는 메소드라 하더라도 서로 다른 이름을 가져야 하기 때문에 개발자 입장에서는 이름을 짓기 어렵고, 이름별로 기능을 구분하여 기억하기도 어렵다. 위 PrintStream클래스처럼 매개변수에 따라 출력하는 메서드를 모두 다르게 정의해야 한다고 생각해보자. 정수형 데이터를 출력하고자 할 때도 자료형의 크기에 따라 printByte(byte a), printShort(short b), printInteger(int c), printLong(long d)로 나누어 메소드를 작성하고 기억해야한다. 하지만 메소드 오버로딩 덕분에 이 모든 메소드를 println()을 이용하여 작성할 수 있다. 또한 이렇게 하나의 메소드명으로 여러 메소드를 정의할 수 있으므로 메소드 이름을 절약할 수 있다.
- 가변인자(varargs)와 오버로딩
- JDK1.5부터 메서드의 매개변수를 동적으로 지정해 줄 수 있게 되었다. 이 기능을 '가변인자(variable arguments)'라고 한다. 가변인자는 '타입... 변수명'과 같은 형식으로 선언한다. 만약 매개변수가 가변인자 하나가 아니고 여러 개라면 매개변수 중 가장 마지막에 가변인자를 선언해야 한다. 그렇지 않으면 컴파일 에러가 발생한다.
- 가변인자를 사용한 메서드는 인자의 개수를 가변적으로 할 수 있어 배열을 인자로 할 수 있고 아예 없어도 된다. 가변인자는 내부적으로 배열을 이용하여 가변인자가 선언된 메서드를 호출하면 배열이 새로 생기므로 꼭 필요한 경우에만 사용해야 한다. 만약 매개변수의 타입을 배열로 한다면 가변인자를 이용한 메서드처럼 인자를 생략할 수 없고 길이가 0인 배열이나 null값을 인자로 지정해줘야 한다.
- 가변인자로 선언한 메서드를 오버로딩하면 두 메서드를 구분할 수 없다. 메서드를 호출했을 때도 구별하지 못해 오류가 발생하기 쉬워 가급적이면 가변인자를 사용한 메서드는 오버로딩하지 않는 것이 좋다.
- 오버로딩이란
- 생성자(Constructor)
- 생성자란?
- 생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'이다. 따라서 인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성시에 실행되어야 할 작업을 위해서도 사용된다. 생성자는 메서드처럼 클래스 내에 선언되며 구조도 메서드와 유사하다. 리턴값이 없다는 점이 메서드와 다르다. 리턴값이 없으면 void를 붙여야 하지만 모든 생성자에 리턴값이 없으므로 void를 사용하지 않는다. 생성자는 인스턴스변수들을 초기화할 뿐 실제로 인스턴스를 생성하는 것은 new 연산자이다.
1. 연산자 new에 의해 메모리(heap)에 Card클래스의 인스턴스가 생성된다.
2.생성자 Card()가 호출되어 수행된다.
3. 연산자 new의 결과로, 생성된 Card인스턴스의 주소가 반환되어 참조변수 c에 저장된다.
- 생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드'이다. 따라서 인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성시에 실행되어야 할 작업을 위해서도 사용된다. 생성자는 메서드처럼 클래스 내에 선언되며 구조도 메서드와 유사하다. 리턴값이 없다는 점이 메서드와 다르다. 리턴값이 없으면 void를 붙여야 하지만 모든 생성자에 리턴값이 없으므로 void를 사용하지 않는다. 생성자는 인스턴스변수들을 초기화할 뿐 실제로 인스턴스를 생성하는 것은 new 연산자이다.
- 기본 생성자(default constructor)
- 컴파일 할 때, 소스파일(*.java)의 클래스에 생성자가 하나도 정의되지 않은 경우 컴파일러는 자동으로 기본 생성자를 추가하여 컴파일한다. 하지만 생성자가 정의되어 있는 경우 기본 생성자를 추가하지 않는다. 기본 생성자가 컴파일러에 의해 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을 때 뿐이다.
- 매개변수가 있는 생성자
- 생성자도 메서드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아 인스턴스를 초기화하는데 사용할 수 있다. 인스턴스마다 각기 다른 값으로 초기화되어야 하는 경우가 많기 때문에 매개변수를 사용한 초기화는 매우 유용하다.
- 생성자에서 다른 생성자 호출하기 - this(), this
- 같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 다음의 조건을 만족한다면 생성자 간에도 서로 호출이 가능하다. 생성자에서 다른 생성자를 호출할 수 있는 조건은 1. 생성자의 이름으로 클래스이름 대신 this를 사용하고, 2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다는 것이다.
class Car{ String color; String gearType; int door; Car(){ this("white", "auto", 4); } Car(String color){ this(color, "auto" 4); } Car(String color, String gearType, int door){ this.color = color; this.gearType = gearType; this.door = door; } }
- 생성자의 매개변수로 인스턴스변수들의 초기값을 제공받는 경우가 많기 때문에 매개변수와 인스턴스 변수의 이름이 일치하는 경우가 많다. 이 때 생성자의 매개변수로 선언된 변수의 이름과 인스턴스 변수와 같다면 두 변수를 서로 구별하기 어렵다. 이런 경우 인스턴스변수 앞에 this를 사용하면 this로 인스턴스 변수에 접근할 수 있다. this는 인스턴스 자신을 가리키는 참조변수이다. 인스턴스의 주소가 저장되어 있다. 모든 인스턴스메서드에 지역변수로 숨겨진 채 존재한다. 참조변수를 통해 인스턴스의 멤버에 접근할 수 있는 것처럼 'this'로 인스턴스변수에 접근할 수 있다.
- static메서드(클래스 메서드)에서는 인스턴스 멤버를 사용할 수 없는 것처럼 this도 사용할 수 없다. 인스턴스 없이 static메서드를 호출할 수 있기때문에 호출된 시점에 인스턴스가 존재하는 지 알 수 없기 때문이다.
- 같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 다음의 조건을 만족한다면 생성자 간에도 서로 호출이 가능하다. 생성자에서 다른 생성자를 호출할 수 있는 조건은 1. 생성자의 이름으로 클래스이름 대신 this를 사용하고, 2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다는 것이다.
- 생성자를 이용한 인스턴스의 복사
- 현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다. 두 인스턴스가 같은 상태를 갖는다는 것은 두 인스턴스의 모든 인스턴스 변수가 동일한 값을 갖고 있다는 것을 의미한다. 인스턴스를 복사하면 서로 같은 상태를 갖지만 독립적으로 메모리 공간에 존재하는 별도의 인스턴스이므로 기존의 인스턴스의 값이 변경되어도 복사한 인스턴스는 영향을 받지 않는다.
- 생성자란?
- 변수의 초기화
- 변수의 초기화
- 변수는 선언과 동시에 적절한 값으로 초기화하는 것이 바람직하나 경우에 따라 필수적이기도 하고 선택적이기도 하다. 멤버변수는 촐기화하지 않아도 변수의 자료형에 맞는 값으로 초기화되어 초기화하지 않아도 사용할 수 있지만 지역변수는 사용하기 전에 반드시 초기화해야한다. 멤버변수(클래스 변수와 인스턴스 변수)와 배열은 초기화가 선택적이지만, 지역변수의 초기화는 필수적이다. 지역변수와 달리 멤버변수를 초기화하는 방법은 명시적 초기화(explicit initialization), 생성자(constructor), 초기화 블럭(initialization block)이 있다.
- 명시적 초기화(explicit initialization)
- 변수를 선언과 동시에 초기화하는 것을 명시적 초기화하라고 한다.
- 초기화 블럭(initialization block)
- 초기화블럭에는 '클래스 초기화 블럭'과 '인스턴스 초기화 블럭'이 있다. 클래스 초기화 블럭은 클래스변수의 초기화에 사용되고, 인스턴스 초기화 블럭은 인스턴스변수 초기화에 사용된다. 인스턴스 초기화 블럭은 클래스 내 블럭{}을 만들고 그 안에 코드를 작성하면 된다. 클래스 초기화 블럭은 인스턴스 초기화 블럭 앞에 static을 붙이면 된다. 클래스 초기화블럭은 클래스가 메모리에 처음 로딩될 때 한번만 수행되며, 인스턴스 초기화 블럭은 생성자와 같이 인스턴스를 생성할 때마다 수행된다.
class Initialization{ static{ /* 클래스 초기화 블럭 */ } { /* 인스턴스 초기화 블럭 */ } }
- 인스턴스 변수의 초기화는 주로 생성자를 사용하고, 인스턴스 초기화블럭은 모든 생성자에서 공통으로 수행해야 하는 코드를 넣는데 사용한다. 모든 생성자에서 공통으로 수행해야하는 코드가 있을 때, 각각의 생성자에 작성하기보다 인스턴스 블럭을 사용하면 코드가 간결해진다. 코드의 중복을 제거하는 것은 코드의 신뢰성을 높여주고, 오류의 발생가능성을 줄여 준다는 장점이 있다. 재사용성을 높이고 중복을 제거하는 것은 객체지향이 추구하는 궁극적인 목표이다.
- 초기화블럭에는 '클래스 초기화 블럭'과 '인스턴스 초기화 블럭'이 있다. 클래스 초기화 블럭은 클래스변수의 초기화에 사용되고, 인스턴스 초기화 블럭은 인스턴스변수 초기화에 사용된다. 인스턴스 초기화 블럭은 클래스 내 블럭{}을 만들고 그 안에 코드를 작성하면 된다. 클래스 초기화 블럭은 인스턴스 초기화 블럭 앞에 static을 붙이면 된다. 클래스 초기화블럭은 클래스가 메모리에 처음 로딩될 때 한번만 수행되며, 인스턴스 초기화 블럭은 생성자와 같이 인스턴스를 생성할 때마다 수행된다.
- 멤버변수의 초기화 시기와 순서
- 클래스변수는 클래스에 대한 정보가 요구될 때, 클래스는 메모리에 로딩되고 기본값 - 명시적 초기화 - 클래스 초기화 블럭의 순서대로 초기화된다. 하지만 해당 클래스가 이미 메모리에 로딩되어 있다면, 또다시 로딩하지 않는다. 따라서 초기화도 다시 수행하지 않는다. 인스턴스변수는 인스턴스가 생성될 때마다 각 인스턴스별로 초기화가 이루어진다. 인스턴스 변수는 기본값 - 명시적 초기화 - 인스턴스 초기화 블럭 - 생성자의 순서로 초기화된다.
- 변수의 초기화
'스터디플래너 > 공부하기' 카테고리의 다른 글
[자바의 정석] Chapter07-2. 객체지향 프로그래밍2 (0) 2022.03.01 [자바의 정석] Chapter07-1. 객체지향 프로그래밍2 (0) 2022.02.21 2월 13일 기록 (0) 2022.02.13 [백준] 4344번 평균은 넘겠지 (0) 2022.02.06 [백준] 1110번 더하기 사이클 (0) 2022.02.03 - 오버로딩(Overloading)