[Java] 클래스(3) - 구성 요소

sobam·2022년 11월 2일
0

자바

목록 보기
17/18
post-thumbnail

📔 학습한 내용을 정리하기 위해 작성하는 게시글입니다.

//클래스 밖에 올 수 있는 3가지
package ...;			// ① 패키지
import ...;				// ② 임포트
class 클래스명 {...} 	// ③ 외부 클래스

//클래스 안에 올 수 있는 4가지
public class A {
	int a = 3;			// ① 필드
    double abc() {...}	// ② 메서드
    A ( ) {...}			// ③ 생성자
    class 클래스명 {...} // ④ 내부 클래스

  목차

  1. 클래스 외부 구성 요소
    1) 패키지(package)
    2) 임포트(import)
    3) 외부 클래스(external class)

  2. 클래스 내부 구성 요소
    1) 필드(field)
    2) 메서드(method)
    3) 생성자(constructor)
    4) 내부 클래스(inner class)
    5) this 키워드, this() 메서드

  3. 메서드 오버로딩


클래스 외부 구성 요소


1. 패키지(package)

: 패키지는 비슷한 목적으로 생성된 클래스 파일들을 한곳에 모아 둔 폴더를 의미한다.

  • 프로젝트를 생성할 때 패키지를 지정했다면 구성 요소에 패키지명이 포함된다.
  • 반드시 주석을 제외한 첫 번째 줄에 위치해야 한다.
  • 클래스의 생성 과정에서 패키지를 생성하지 않았다면, 즉 디폴트 패키지를 사용하면 생략된다.
  • 클래스가 저장되는 공간이 분리돼 클래스명의 충돌을 방지할 수 있다. (클래스명이 같더라도 경로가 다르므로 충돌 문제 발생하지 X)

자바가 제공하는 API의 대표적인 패키지에는 기본 클래스들을 묶어 놓은 java.lang, 유용한 확장 클래스들을 묶어 놓은 java.util, 자바 그래픽과 관련된 클래스들을 묶어 놓은 java.swing, javafx, 자바의 입출력 클래스들을 묶어 놓은 java.io, java.nio 패키지 등이 있다.

2. 임포트(import)

: 다른 패키지 내의 클래스를 사용하기 위한 문법 요소이다.

  • 이클립스에서는 Ctrl + Shift + o 를 이용해 외부 패키지에 위치하고 있는 클래스를 자동으로 임포트할 수 있다.
  • 소스 코드상에서 패키지 구문의 다음 줄에 위치한다.

다른 패키지의 클래스를 사용하는 방법

1) 클래스의 풀네임 사용

클레스의 풀네임

1. import.패키지명.클래스명;
2. import.패키지명.*;
package sec01_packageimport.common;

public class A {
	public int m = 3;
    public int n = 4;
    public void print() {
		System.out.println("임포트");
	}
}
package sec01_packageimport.EX01_PackageImport_1;

public class PackageImport_1 {
	public static void main(String[] args) {
		//객체 생성
        //A a = new A(); //오류
        sec01_packageimport.common.A a = new sec01_packageimport.common.A();
        
        //멤버 활용
        System.out.println(a.m);
        System.out.println(a.n);
        a.print();
	}
}
3
4
임포트

다른 패키지에서 클래스를 사용하려면 반드시 public class로 선언되어야 한다.
다른 패키지의 클래스를 사용할 때는 패키지명을 포함한 풀네임을 사용해야 한다.

2) 임포트 사용

위 1) 예제에서 import 패키지명.클래스명, 즉, sec01_packageimport.common.A를 표기해 놓으면 이후 A a = new A()와 같이 A의 클래스명만 사용할 수 있다.

  • 패키지 내의 모든 클래스를 임포트하고 싶다면 * 를 사용해 sec01_packageimport.common.* 와 같이 표현한다.
  • * 기호로 임포트할 때에는 하위 폴더는 임포트 되지 않는다. 상위 폴더와 하위 폴더를 각각 따로 임포트해야 한다.
  • 같은 패키지 내에 같은 이름의 클래스를 중복해서 임포트할 수 없다. (방법 1을 사용하거나 방법 1과 2를 혼용해야 한다.)
  • 자바에서는 가장 많이 사용하는 java.lang 패키지에 대해서는 import 문을 사용하지 않아도 클래스 이름만으로 사용할 수 있도록 하고 있다.
package sec01_packageimport.EX02_PackageImport_2;

import sec01_packageimport.common.A;

public class PackageImport_2 {
	public static void main(String[] args) {
    	//객체 생성
        A a = new A(); //클래스 A를 임포트 했으므로 가능
        
        //멤버 활용
        System.out.println(a.m);
        System.out.println(a.n);
        a.print();
    }
}
3
4
임포트

3. 외부 클래스(external class)

: 외부 클래스는 public 클래스의 외부에 추가로 정의한 클래스이다.

  • 1개의 자바 소스 파일에는 최대 1개의 public 클래스만 존재할 수 있고, 그 클래스 명은 파일명과 일치해야 한다.
    → 1개의 소스 파일 안에서 public 클래스를 제외한 모든 클래스는 외부 크랠스이다.
  • 외부 클래스에는 public 키워드를 붙일 수 없다.
    public 클래스가 아니면 다른 패키지에서 임포트할 수 없으므로 외부 클래스는 같은 패키지 안에서만 사용할 수 있다.
  • public 여부와 관계없이 같은 패키지 내에서는 객체의 생성 및 활용이 가능하다.
  • 다른 패키지에서 외부 클래스 A의 객체를 생성하고 싶다면 별도의 소스 파일로 분리해야 한다.
	package abc.bcd;
    class ABC { //외부 클래스는 다른 클래스에서 임포트 불가능
    	//...
    }
    public class BCD { //public 클래스는 다른 패키지에서 임포트 가능
    	//...
    }

클래스 외부에는 이들 3가지 구성 요소(패키지, 임포트, 외부 클래스)가 모두 오거나 일부 또는 하나도 오지 않아도 된다. (그 외에는 어떠한 요소도 올 수 없음)

소스 코드상에서 패키지, 임포트, 외부 클래스 순으로 순서를 지켜서 위치시켜야 한다.



클래스 내부 구성 요소


1. 필드(field)

: 클래스의 특징(속성)을 나타내는 변수다. 만일 이 클래스가 한 사람에 관련된 정보를 담고 있다면, 필드값으로 나이(int age = 20) 등이 포함될 수 있을 것이다.

  • 필드는 '클래스에 포함된 변수'로, 객체의 속성값을 지정할 수 있다.

필드와 지역변수

필드지역변수
선언 위치클래스의 중괄호 안메서드 중괄호 안
생성되는 메모리의 위치힙 메모리의 객체 내부스택 메모리
초깃값초기화하지 않아도 강제 초기화됨초기화하지 않으면 오류 발생

힙 메모리에는 빈 공간이 저장될 수 없기 때문에 힙 메모리에 위치하는 필드는 강제로 초기화된다.

클래스 변수와 인스턴스 변수의 초깃값

변수의 타입초깃값
char'\u0000'
byte, short, int0
long0L
float0.0F
double0.0 또는 0.0D
booleanfalse
배열, 인스턴스 등null

2. 메서드(method)

: 클래스가 지니고 있는 기능(함수)을 나타낸다. 한 사람에 관련된 클래스라면 일하기(void working( ) {...}) 등이 포함될 수 있다.

자바제어자 리턴(반환)타입 메서드명(입력매개변수) {
	메서드 내용
}
public static int sum(int a, int b) {
	//메서드 내용
}

1) 메서드 정의

  • 리턴 타입은 메서드 종료 이후 변환(또는 반환)되는 값의 자료형을 의미한다.
  • 예제는 '입력값으로 int형 2개의 값을 입력받아 처리하며, 메서드가 종료된 이후에 int 값을 리턴하라'는 의미이다.
  • 리턴이 void가 아닐 때 메서드 안에는 반드시 'return 리턴값'의 코드가 있어야 한다.
  • 리턴 타입이 void일 때, return은 '메서드를 종료하라.'는 의미이다.

void 리턴 타입은 리턴하지 않는다는 것을 의미한다.

메서드명은 변수명 선정 규칙과 동일, 소문자로 시작하는 게 관례이다.

2) 메서드 호출

클래스 외부에서 메서드 호출
: 클래스 외부에서 메서드를 사용하려면 먼저 객체를 생성해야 한다.

클래스 내부에서 메서드 호출
: 클래스 내부에 있는 메서드끼리는 객체를 생성하지 않고 서로를 호출할 수 있다. (같은 멤버이기 때문)
→ 같은 멤버끼리는 클래스 내부에서 객체를 생성하지 않고 서로를 호출할 수 있다.

3. 생성자(constructor)

: 생성자(A( ) {...})는 클래스의 객체를 생성하는 역할을 담당한다. 객체 내에 포함되는 필드의 초기화는 주로 생성자 내에서 수행한다.

클래스명(입력매개변수) { //입력매개변수 생략 가능
}
class A {
	A() {
		//...
	}

}
  • 생성자를 포함하지 않는 클래스에서는 컴파일러가 기본 생성자(default constructor, 입력매개변수가 없는 생성자)를 자동으로 추가해 준다.

    	클래스이름() {} //기본 생성자
  • 생성자는 초기화를 위한 데이터를 인수로 전달받을 수 있다.

  • 객체를 초기화하는 방법이 여러 개 존재할 경우에는 하나의 클래스가 여러 개의 생성자를 가질 수 있다. (생성자도 하나의 메서드이므로, 메서드 오버로딩이 가능함)

생성자 작성 시 지켜야 할 문법적 규칙 두 가지
1. 반드시 클래스명과 동일한 이름으로 지어야 한다.
2. 리턴 타입이 없다.(메서드와 구분되는 점)

'리턴 타입이 없다' 와 '리턴하지 않는다(void)는 다른 뜻이다.

4. 내부 클래스(inner class)

: 클래스의 내부에도 클래스가 포함될 수 있다. 이 클래스를 특별히 '내부 클래스'라고 한다.

내부에 올 수 있는 4가지 구성 요소들 중 생성자를 제외한 3가지 요소를 '클래스의 멤버'라고 한다.

5. this 키워드, this() 메서드

1) this 키워드

this 키워드는 인스턴스가 자기 자신을 참조하는 데 사용하는 변수이다. this 키워드는 이 클래스를 키반으로 생성된 해당 인스턴스의 주소를 가리킨다.

  • 클래스 내부에서 멤버를 활용할 때 this.를 생략하면 컴파일러가 자동으로 this.를 추가해 준다.
//클래스 내부에서 필드, 메서드 앞에 자동으로 붙는 this 키워드

class A {
	int m;
	int n;
	void init(int a, int b) {
		int c;
		c = 3;
		this.m = a; //this.를 생략했을 때 자동으로 추가
		this.n = b; //this.를 생략했을 떄 자동으로 추가
	}
	void work() {
		this.init(2, 3); //this.를 생략헀을 때 자동으로 추가
	}
}
public class ThisKeyword_1 {
	public static void main(String[] args) {
		//클래스 객체 생성
		A a = new A();
		//메서드 호출 / 필드값 활용
		a.work();
		System.out.println(a.m);
		System.out.println(a.n);
	}
}

명시적으로 this 키워드를 붙여 줘야 하는 경우

class A {
	int m;
    int n;
    void init(int m, int n) {
	m = m;
    n = n;
    }
}

필드와 지역 변수를 모두 사용할 수 있고, 이름이 같을 때에는 컴파일러가 이들 모두를 지역 변수로 인식한다. 그럼 this 키워드가 자동으로 추가되지 않아서 지역 변수에 지역 변숫값을 다시 대입하는 형태가 되어 버린다.

그러므로 넘겨받은 지역 변수와 필드명이 동일할 때는 필드에 this 키워드를 붙여 표기해야 한다.

(자바에서 제공하는 대부분의 API에는 메서드의 지역 변수명이 필드명과 동일하게 구성되어 있다.)

2) this() 메서드

this() 메서드는 자신이 속한 클래스 내부의 다른 생성자를 호출한다.

  • this() 메서드를 이용해 생성자의 중복을 제거할 수 있다.

this() 메서드 작성 시 지켜야 할 문법적 규칙 두 가지
1. 생성자의 내부에서만 사용할 수 있다. (=생성자의 내부에서만 또 다른 생성자를 호출할 수 있다.)
2. 생성자의 첫 줄에 위치해야 한다.
→ 지키지 않으면 오류 발생

//클래스 정의
class A {
	A() {
    	System.out.println("첫 번째 생성자");
    }
    A(int a) {
    	this(); //반드시 생성자의 첫 줄에 위치해야 함.
    	System.out.println("두 번째 생성자");
    }
    /*
    void abc() {
    	this(); // 메서드에서는 this() 메서드 사용 불가능
    }*/
}
public class ThisMethod_1 {
	public static void main(String[] args) {
    	//객체 생성
        A a1 = new A(); //첫 번째 생성자 호출
        System.out.println();
        A a2 = new A(3); //두 번재 생성자 호출(생성자의 내부에서 첫 번째 생성자 호출)
    }
}
//실행결과
첫 번째 생성자

첫 번째 생성자
두 번째 생성자
//this() 메서드를 이용해 생성자의 중복 제거
class A {
	int m1, m2, m3, m4;
    A() {
    	m1 = 1;
        m2 = 2;
        m3 = 3;
        m4 = 4;
    }
    A(int a) {
    	this();
        m1 = a;
    }
    A(int a, int b) {
    	this(a);
    	m2 = b;
    }
}



메서드 오버로딩


리턴타입 메서드명 (자료형 변수명, 자료형 변수명, ...) {
} //메서드 시그니처 : 메서드명, 자료형, 자료형 ...
int sum (int a, int b) {
	return 3;
} //메서드 시그니처 : sum, int, int

1. 메서드 시그니처(method signature)

메서드 시그니처란 메서드의 선언부에 명시되는 매개변수의 리스트(메서드명, 입력매개변수의 자료형)를 가리킨다.

2. 메서드 오버로딩(method overloading)

메서드 오버로딩(overloading)이란 여러 개의 동일한 이름의 메서드를 같은 공간에 중복하여 정의하는 것을 의미한다.

  • 호출할 때 넘겨 주는 입력매개변수에 따라 호출될 메서드가 선택된다.
  • 자바에서는 한 클래스 내에 같은 이름의 메서드를 둘 이상 가질 수 없지만, 매개변수의 개수나 타입을 다르게 하면 동일한 이름의 메서드를 작성할 수 있다.
    → 서로 다른 시그니처를 갖는 메서드를 같은 이름으로 정의하는 '메서드 오버로딩'
  • 메서드 오버로딩을 사용함으로써 메서드에 사용되는 이름을 절약할 수 있다.
  • 메서드를 호출할 때 전달해야 할 매개변수의 타입이나 개수에 대해 크게 신경쓰지 않고 호출할 수 있다.
  • 메서드 오버로딩은 객체 지향 프로그래밍의 특징 중 하나인 다형성(polymorphism)을 구현하는 방법 중 하나이다.

즉, 메서드 오버로딩은 서로 다른 시그니처를 갖는 여러 메서드를 같은 이름으로 정의하는 것이라고 할 수 있다.

리턴 타입이 시그니처에 포함되지 않은 이유는 메서드 호출 과정에서 리턴 타입을 사용하지 않기 때문이다. 리턴 타입으로는 메서드를 구분할 수 없다.

만일 메서드의 시그니처는 같고, 반환 타입은 다른 경우라면?
: 메서드 오버로딩이 성립되지 않음.

메서드 오버로딩의 대표적인 예) println() 메서드

3. 메서드 오버로딩의 조건

자바에서 메서드 오버로딩이 성립하기 위해서는 다음과 같은 조건을 만족해야 한다.

메서드 오버로딩이 성립하기 위해 만족해야 할 조건 두 가지
1. 메서드의 이름이 같아야 한다.
2. 메서드의 시그니처, 즉 매개변수의 개수 또는 타입이 달라야 한다.

메서드 오버로딩은 반환 타입과는 관계가 없다.
만약 메서드의 시그니처는 같은데 반환 타입만이 다른 경우에는 오버로딩이 성립하지 않는다.

자바에서 제공하는 println() 메서드의 오버로딩

System.out.println(true);
System.out.println(3);
System.out.println(5.8);


🔔 Reference

<Do it! 자바 완전 정복>
http://www.tcpschool.com/java/java_methodConstructor_this

0개의 댓글

관련 채용 정보