무작정 개발.Vlog

자바의 정석 | Ch 06 - 객체지향 프로그래밍1-2

by 무작정 개발
반응형

4. 오버로딩(OverLoading)

4.1 오버로딩이란?

 

오버로딩(overloading)

 

한 클래스 내에 같은 이름의 메서드를 여러개 정의하는 것.

한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있더라도 매개변수의 개수 또는 타입이 다르면,

같은 이름을 사용해서 메서드를 정의할 수 있다.

 

4.2 오버로딩(overloading)의 조건

오버로딩의 조건

1. 메서드 이름이 같아야 한다.
2, 매개변수의 개수 또는 타입이 달아야 한다.
3, 반환타입은 영향 없다.

 

4.3 오버로딩(overloading)의 예

매개변수는 다르지만 같은 의미의 기능을 수행하는 오버로딩의 예로 가장 대표적인 것은 println메서드이다.

println메서드를 호출할 때 매개변수로 지정하는 값의 타입에 따라서 호출되는 println메서드가 달라진다. PrintStream클래스에는 어떤 

종류의 매개변수를 지정해도 출력할 수 있도록 아래와 같이 10개의 오버로딩된 println메서드를 정의해놓고 있다.

  • void println()
  • void println(boolean x)
  • void println(char x)
  • void println(char [] x)
  • void println(double x)
  • void println(float x)
  • void println(int x)
  • void println(long x)
  • void println(Object x)
  • void println(String x)

println메서드를 호출할 때 매개변수로 넘겨주는 값의 타입에 따라서 위의 오버로딩된 메서드들 중의 하나가 선택되어 실행되는 것이다.

 

4.4 오버로딩(overloading) 장점

 

메서드도 변수처럼 단지 이름만으로 구별된다면, 한 클래스내의 모든 메서드들은 이름이 달라야한다. 모두 근본적으로는 같은 기능을 하는

메서드들이자만, 서로 다른 이름을 가져야 하기 때문에 이름을 짓기 어렵고, 이름을 일일이 구분해서 기억해야 하기 때문에 힘들다.

하지만 오버로딩(overloading)을 통해 여러 메서드들이 println이라는 하나의 이름으로 정의될 수 있다면, 사용하기 매우 편해진다. 또한 메서드들은 이름이 같으니, 같은 기능을 하겠구나 하고 쉽게 분류가 가능하다.  이제 하단 예제를 풀어보자!

 

//예제6-21/ch6/OverLoadingtest.java
package Chapter06;

public class Overloadingtest {
    public static void main(String[] args) {
        MyMath3 mm = new MyMath3();
        System.out.println("mm.add(3,3) 결과:"    + mm.add(3,3));
        System.out.println("mm.add(3L,3) 결과:"    + mm.add(3L,3));
        System.out.println("mm.add(3,3L) 결과:"    + mm.add(3,3L));
        System.out.println("mm.add(3L,3L) 결과:"    + mm.add(3L,3L));

        int [] a = {100, 200, 300};
        System.out.println("mm.add(a) 결과: " + mm.add(a));
    }
}

class MyMath3 {
    int add(int a, int b) {
        System.out.println("int add(int a, int b) - ");
        return a + b;
    }

    long add(int a, long b) {
        System.out.println("int add(int a, long b) - ");
        return a + b;
    }

    long add(long a, int b) {
        System.out.println("long add(long a, int b) - ");
        return a + b;
    }

    long add(long a, long b) {
        System.out.println("long add(long a, long b) - ");
        return a + b;
    }

    int add(int[] a) {
        System.out.print("int add(int [] a) - ");
        int result = 0;
        for (int i = 0; i < a.length; i++) {
            result += a[i];
        }
        return result;
    }
}

4.5 가변인자(varargs)와 오버로딩

가변인자는 '타입... 변수명'과 같은 형식으로 선언하며, PrintStream클래스의 printf()가 대표적인 예이다.

 

5. 생성자(Constructor)

5.1 생성자란?

생성자

인스턴스가 생성될 때마다 호출되는 [ 인스턴스 초기화 메서드 ] 이다.

주로 인스턴스변수의 초기화 작업에 주로 사용되고, 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다.

생성자 또한 매서드처럼 클래스 내에 선언된다.

 

생성자 규칙

  • 생성자 이름이 클래스이름과 같아야한다.
  • 생성자는 리턴값이 없다(void 안붙임)
  • 모든 클래스는 반드시 생성자를 가진다.

생성자는 다음과 같이 정의한다. 생성자도 오버로딩이 가능하므로 하나의 클래스에 여러 개의 생성자가 존재할 수 있다.

클래스이름(타입 변수명, 타입 변수명, ...) {
  // 인스턴스 생성 시 수행될 코드,
  // 주로 인스턴스 변수의 초기화 코드를 적는다.
}

class Card {
	 Card() {   // 매개변수가 없는 생성자.
            ....
     }
     
     Card(String k, int num) {    // 매개변수가 있는 생성자.
            ...
     }
      ...
}

연산자 new가 인스턴스를 생선하는 것이지 생성자가 인스턴스를 생성하는 것이 아니다.

Card클래스의 인스턴스를 생성하는 코드를 예로 들어, 수행되는 과정을 단계별로 나누어 보면 다음과 같다.

Card c = new Card();

1. 연산자 new에 의해서 메모리(heap)에 Card클래스의 인스턴스가 생성된다.
2. 생성자 Card()가 호출되어 수행된다.
3. 연산자 new의 결과로, 생성된 Card인스턴스의 주소가 반환되어 참조변수 c에 저장된다.

인스턴스를 생성하기위해 사용해왔던 '클래스이름()'이 생성자였던 것이다. 인스턴스를 생성할 때는 반드시 클래스 내에 정의된 생성자 중의

하나를 선택하여 지정해야 한다.

 

5.2 기본 생성자(default constructor)

 

모든 클래스에는 반드시 1개 이상의 생성자가 정의되어 있어야 한다. 그러나 지금까지 클래스에 생성자를 정의하지 않고도 인스턴스를 생성할 수 있었던 이유는 컴파일러가 제공하는 '기본 생성자(default constructor)' 덕분이다.

 

특징

  • 클래스이름() { } ... (매개변수)도 {하는일} 도 없음
  • 매개변수가 없는 생성자
  • 생성자가 하나도 없을 때만 컴파일러가 자동추가를 해줌.
  • 기본 생성자가 컴파일러에 의해서 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을 때 뿐이다.

 

5.3 매개변수가 있는 생성자

 

생성자도 메서드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아서 인스턴스의 초기화 작업에 사용 할 수 있다. 인스턴스마다 각기

다른 값으로 초기화되어야하는 경우가 많기 때문에 매개변수를 사용한 초기화는 매우 유용하다.

 

매개변수가 있는 생성자

  • 인스턴스를 생성하는 동시에 원하는 값으로 초기화 할 수 있게된다.
  • 인스턴스 생성 후 인스턴스변수의 값을 변경하는 것보다 이게 코드가 더 간결하다.
//예제6-24/ch6/Cartest.java
package Chapter06;

class Car {
    String color;		// 색상
    String gearType;	// 변속기 종류 - auto(자동), manual(수동)
    int door;			// 문의 개수

    Car() {}
    Car(String c, String g, int d) {
        color = c;
        gearType = g;
        door = d;
    }
}

class CarTest {
    public static void main(String[] args) {
        Car c1 = new Car();
        c1.color = "white";
        c1.gearType = "auto";
        c1.door = 4;

        Car c2 = new Car("white", "auto", 4);

        System.out.println("c1의 color=" + c1.color + ", gearType=" + c1.gearType+ ", door="+c1.door);
        System.out.println("c2의 color=" + c2.color + ", gearType=" + c2.gearType+ ", door="+c2.door);
    }
}

 

5.4 생성자에서 다른 생성자 호출하기 - this(), this

 

같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능하다.

 

규칙

  • 생성자에서 같은 클래스의 다른 생성자를 호출할 때, 클래스이름 대신 this를 사용함.
  • 한 생성자에서 다른 생성자를 호출 시 반드시 첫 줄에서만 호출이 가능. ( 다른 생성자로 인해 호출이전의 초기화 직업이                       무의미해지므로 첫줄에서 호출하기)
//예제6-25/ch6/CarTest2.java
package Chapter06;

class Car {
    String color;		// 색상
    String gearType;	// 변속기 종류 - auto(자동), manual(수동)
    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;
    }
}

class CarTest2 {
    public static void main(String[] args) {
        Car c1 = new Car();
        Car c2 = new Car("blue");

        System.out.println("c1의 color=" + c1.color + ", gearType=" + c1.gearType+ ", door="+c1.door);
        System.out.println("c2의 color=" + c2.color + ", gearType=" + c2.gearType+ ", door="+c2.door);
    }
}

생성자 Car()에서 또 다른 생성자 Car(String color, String gearType, int door)를 호출하였다. 이처럼 생성자간의 호출에는 생성자의 이름 대신 this를 사용해야만 하므로 'Car'대신 'this'를 사용했다. 그리고 생성자 Car()의 첫째 줄에서 호출하였다는 점을 눈여겨봐야한다.

 

참조변수 this

  • 인스턴스 변수(iv)와 지역변수의 이름이 같을 때 구별하기위해 사용 / this가 붙으면 인스턴스 변수(iv)이다. 안붙이면 매개변수와      가까운 지역변수이다.
  • 인스턴스 자신을 가르키는 참조변수, 인스턴스(객체)의 주소가 저장되어 있다.
  • 인스턴스메서드에서 사용함 / static 메서드(클래스 메서드)에서는 사용 불가

@핵심@

this 와 this() 는 비슷하게 생겼을 뿐 완전히 다른 것이다. this 는 참조변수, this()는 생성자이다.

 

6. 변수의 초기화

6.1 변수의 초기화

 

변수를 선언하고 처음으로 값을 저장하는 것을 '변수의 초기화'라고 한다. 변수의 초기화는 경우에 따라서 필수적이기도 하고 선택적이기도 하지만, 가능하면 선언과 동시에 적절한 값으로 초기화 하는 것이 바람직하다.

맴버변수는 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지므로 초기화하지 않고 사용해도 되지만,

지역변수는 사용하기 전에 반드시 초기화해야 한다.

 

맴버변수(iv, cv)는 자동초기화(초기화 선택적)

지역변수는 수동으로 초기화(초기화 필수)

 

<각 타입의 기본값>

자료형 기본값
boolean false
char ' \u0000 '
byte, short, intt 0
long 0L
float 0.0f
double 0.0d 또는 0.0
참조형 변수 null

맴버 변수의 초기화 방법

 

1. 명시적 초기화

2. 생성자

3. 초기화 블럭

  - 인스턴스 초기화 블럭 : 인스턴스변수를 초기화 하는데 사용 ( 인스턴스변수의 복잡한 초기화에 사용)

  - 클래스 초기화 블럭 : 클래스변수를 초기화 하는데 사용 ( 클래스변수의 복잡한 초기화에 사용)

 

6.4 맴버변수의 초기화 시기와 순서

 

초기화가 수행되는 시기와 순서

클래스변수의 초기화 시점 : 클래스가 처음 로딩될 때 단 한번 초기화 된다.
인스턴스변수의 초기화시점 : 인스턴스가 생성될 때마다 각 인스턴스별로 초기화가 이루어진다.

클래스변수의 초기화순서 : 기본값 -> 명시적초기화 -> 클래스 초기화 블럭
인스턴스변수의 초기화순서 : 기본값 -> 명시적초기화 -> 인스턴스 초기화 블럭 -> 생성자

 

멤버변수의 초기화

 

1. 자동초기화

2. 간단초기화

3. 복잡초기화 --  { } 거의 안씀

                      -- static { }    ..  cv(클래스변수) :클래스가 처음 메모리에 올라갈 때 단 한번 사용

                      -- 생성자() { } ..  iv(인스턴스변수) : 인스턴스 생성될 때마다 사용

 

멤버변수의 초기화시기와 순서

멤버 변수의 초기화 시기와 순서

  • 클래스변수 초기화(1~3) : 클래스가 처음 메모리에 로딩될 때 차례대로 수행됨.
  • 인스턴스변수 초기화(4~7) : 인스턴스를 생성할 때 차례대로 수행됨

|중요| 클래스변수는 항상 인스턴스변수보다 항상 먼저 생성되고 초기화 된다.

 

//예제6-31/ch6/DocumentTest.java
package Chapter06;

class Document {
    static int count = 0;
    String name;     // 문서명(Document name)

    Document() {     // 문서 생성 시 문서명을 지정하지 않았을 때
        this("제목없음" + ++count);
    }

    Document(String name) {
        this.name = name;
        System.out.println("문서 " + this.name + "가 생성되었습니다.");
    }
}

class DocumentTest {
    public static void main(String args[]) {
        Document d1 = new Document();
        Document d2 = new Document("자바.txt");
        Document d3 = new Document();
        Document d4 = new Document();
    }
}

 

 

객체지향 1 끝!

반응형

블로그의 정보

무작정 개발

무작정 개발

활동하기