[Java]객체지향 프로그래밍 1

황세호·2021년 5월 13일
0

클래스 메서드(static메서드)와 인스턴스 메서드


  • 클래스 메서드클래스 변수처럼 객체를 생성하지 않고도 호출이 가능하다.

  • 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다.
    * 모든 인스턴스에서 같은 값이 유지되어야 하는 변수는 static을 붙여서 클래스변수로 정의해야 한다.

  • 클래스 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
    * static이 붙은 변수는 클래스가 메모리에 올라갈 때 이미 자동적으로 생성되기 때문이다.

  • 클래스 메서드는 인스턴스 변수를 사용할 수 없다.
    클래스메서드는 인스턴스 생성 없이 호출 가능하므로 클래스 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수도 있다.
    그래서 인스턴스 변수의 사용을 금지한다.

  • 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
    인스턴스 변수를 필요로 하지 않는다면 static을 붙이는 것이 좋다. (메서드 호출시간이 짧아지므로 성능이 향상)
    static을 안 붙인 메서드는 실행 시 호출되어야 할 메서드를 찾는 과정이 추가적으로 필요하기 떄문에 시간이 더 걸린다.

클래스 멤버와 인스턴스 멤버간의 참조와 호출


  • 같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다.
  • 단, 클래스멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다.
Class TestClass{

	void instanceMethod(){}
	static void staticMethod(){}

	void instanceMethod2() {
		instanceMethod();
		staticMethod();
	}

	static void staticMethod2() {
		instanceMethod();          // 에러!! 인스턴스메서드를 호출할 수 없다.
		staticMethod();            // static 메소드는 호출할 수 있다.
	}
}
Class TestClass2 {
	int iv;
	static int cv;

	void instanceMethod() {
		System.out.println(iv);
		System.out.println(cv);
	}

	static void staticMethod() {
		System.out.println(iv);      // 에러!! 인스턴스 변수를 사용할 수 없다.
		System.out.println(cv);      // static 변수는 사용할 수 있다.
	}
}

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


  • 기존에는 메서드의 매개변수 개수가 고정적이었으나, JDK1.5부터 동적으로 지정해줄 수 있게 되었다.
  • 가변인자는 ’타입… 변수명’과 같은 형식으로 선언한다.
public PrintStream printf(String format, Object... args) {...}
위와 같이 가변인자 외에도 매개변수가 더 있다면, 가변인자를 매개변수 중에서 제일 마지막에 선언해야 한다. 그렇지 않으면, 컴파일 에러가 발생한다. (가변인자인지 아닌지를 구별할 방법이 없기 때문)

만일 여러 문자열을 하나로 결합하여 반환하는 concatenate메서드를 작성한다면, 아래와 같이 작성해야할 것이다.

String concatenate(String s1, String s2) {...}
String concatenate(String s1, String s2, String s3) {...}
String concatenate(String s1, String s2, String s3, String s4) {...}

이럴 때, 가변인자를 사용하면 된다.

String concatenate(String... str) {...}

아마 눈치 챘을 것인데, 가변인자는 내부적으로 배열을 이용한다. 그래서 가변인자가 선언된 메서드를 호출할 때마다 배열이 새로 생성된다. (가변인자가 편리하지만, 이런 비효율이 숨어있으므로 꼭 필요한 경우에만 가변인자를 사용하자)

그러면 가변인자는 아래와 같이 매개변수의 타입을 배열로 하는 것과 어떤 차이가 있는가?

String concatenate(String[] str) {...}

String result = concatenate(new String[0]);  // 인자로 배열을 지정
String result = concatenate(null);           // 인자로 null을 지정
String result = concatenate();               // 에러. 인자가 필요함.
매개변수의 타입을 배열로 하면, 반드시 인자를 지정해줘야 하기 때문에, 위의 코드에서처럼 인자를 생략할 수 없다. 그래서 null이나 길이가 0인 배열을 인자로 지정해줘야 하는 불편함이 있다.

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


this()

같은 클래스의 멤버들 간에 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능하다. 단, 다음의 두 조건을 만족시켜야 한다.

  • 생성자의 이름으로 클래스이름 대신 this를 사용한다.
  • 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.

다음의 코드는 생성자를 작성할 때 지켜야하는 두 조건을 모두 만족시키지 못했기 때문에 에러가 발생한다.

Car(String color) {
	door = 5;
	Car(color, "auto", 4);    // 에러1. 생성자의 두 번째 줄에서 다른 생성자 호출
                            // 에러2. this(color, "auto", 4);로 해야한다.
}
  • 생성자 내에서 초기화 작업 도중에 다른 생성자를 호출하게 되면, 호출된 다른 생성자 내에서도 멤버변수들의 값을 초기화 한다.
  • 그렇게 되면 다른 생성자를 호출하기 이전의 초기화 작업이 무의미해질 수 있다.
  • 이렇기에, 첫 번째 줄에서만 다른 생성자의 호출이 가능하다.

this

Car(String color, String gearType, int door) {
	this.color = color;
	this.gearType = gearType;
	this.door = door;
}
  • this는 참조변수로 인스턴스 자신을 가리킨다.
  • 참조변수를 통해 인스턴스의 멤버에 접근할 수 있는 것처럼 this로 인스턴스 변수에 접근할 수 있는 것이다. (static메서드에서는 인스턴스 멤버들을 사용할 수 없는 것처럼 this 역시 사용할 수 없음)

this
인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어 있다.
모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재한다.

this()
생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.

this와 this()는 비슷하게 생겼을 뿐, 완전히 다른 것이다.
profile
Developer

0개의 댓글