[Java] 클래스의 기본구조

Geehyun(장지현)·2024년 1월 26일
0

Java

목록 보기
5/12
post-thumbnail

클래스의 개념

객체(Object)는 사용할 수 있는 실체를 의미하며, 클래스란 이런 객체를 만들기 위한 설계도 또는 청사진 같은 개념입니다.

💡 프로그래밍 문법의 발전 과정

  • 변수 : 다양한 형태의 데이터를 저장하기 위해 데이터를 저장할 수 있는 변수라는 개념이 생겼습니다.
  • 배열 : 데이터가 많아져 이를 쉽게 관리하기 위해 같은 자료형끼리의 값을 묶어 관리할 수 있는 배열의 개념이 생겼습니다.
  • 구조체 : 배열과 변수들 각기 다른 자료형을 묶어 관리할 수 있는 구조체의 개념이 생겼습니다.
  • 클래스 : 다양한 자료형의 데이터를 묶어 관리할 수 있을 뿐만 아니라 데이터를 처리하는 다양한 기능까지 함께 관리할 수 있는 클래스라는 개념이 생기게되었습니다.

객체지향 프로그래밍 언어

Java는 객체지향 프로그램잉 언어로 프로그램을 객체 단위로 수행하는 방식으로 구성되었습니다.

  • 절차지향 프로그래밍 : Procedural Programming(PP)로 순서에 맞춰 단계적으로 실행하도록 명령어를 나열하는 방식 입니다.
  • 객체지향 프로그래밍 : Object-Oriented Programming(OOP)으로 객체 단위로 프로그래밍을 하는 방식 입니다.
    • OOP의 특징 : 추상화, 상속, 다형성, 캡슐화

Java에서는 객체지향 문법 요소로 크게 클래스인터페이스를 제공하고 있습니다.

클래스의 구조

클래스는 class 클래스명 {...}으로 작성할 수 있으며, 클래스명은 관습적으로 영문대문자로 시작하는 방식으로 사용합니다.

클래스는 기본적으로 아래의 구조로 구성되어있습니다.

Package ...;               // 패키지
import ...;                // 임포트
class 클래스명 {...};       // 외부 클래스

public class A {      
	int a = 3;            // 필드
    double ab() {...};    // 메서드
    A();                  // 생성자
    class B {...};        // 이너 클래스
}

클래스 내부 구성요소
1. 필드 : 멤버변수라고도 하며, 클래스 내부에 선언된 변수를 말합니다. 이 때 클래스 내 메서드 안에서 사용되는 지역변수는 포함되지 않습니다.
2. 메서드 : 멤버함수라고도 하며, 클래스 내 함수들을 말합니다.
3. 생성자 : 해당 클래스의 객체를 생성하는 역할을 담당하며, 필요할 경우 객체에 포함되는 필드의 초기화도 수행하게끔 할 수 있습니다.
4. 이너 클래스 : 클래스 내부에 포함되어있는 클래스입니다.

클래스 외부 구성요소
1. 패키지 : 해당 소스파일의 패키지위치가 표시됩니다. 디폴트 패키지를 사용할 경우 표시되지 않습니다.
2. 임포트 : 다른 패키지의 클래스를 사용하고자 할 때 임포트해올 수 있습니다.
3. 외부 클래스 : 한 소스파일에 클래스는 여러개 올 수 있습니다.

클래스의 내부 구성요소

클래스 내부에는 필드, 메서드, 이너클래스의 멤버 요소와 생성자로 구분됩니다.

필드

필드(field) 클래스에 포함되어있는 변수를 말하며, 클래스 내부 메서드 안에서 사용되는 지역변수는 포함되지 않습니다.

💡 필드와 지역변수

class A {
	int a = 2;        // 필드 a
    void test() {
    	int b = 3;   // 지역변수 b
    }
}

클래스의 중괄호 안에 선언된 변수를 필드라고 하며, 메서드의 중괄호 안에 선언된 변수를 지역변수라고 합니다.

  • 필드 : 클래스 중괄호 내 어디든 사용가능하며, 힙 영역 객체 내부에 저장됩니다.
  • 지역변수 : 해당 메서드 중괄호 내에서만 사용이 가능하며. 스택 영역에 저장됩니다.
  • 프레임 : 한 개의 메서드 내 선언된 모든 지역변수를 말합니다.
    해당 메서드이 실행이 종료되면 JVM은 해당 메서드의 프레임 자체를 삭제합니다.

메서드

메서드는 클래스 내부에 정의된 함수로 아래의 구조를 가집니다.

//작성법
자바제어자 리턴타입 메서드명(매개변수명) {
	메서드 내용
}

//작성예시
public void printNumber(int...a) {
    for(int i : a) {
    	System.out.println(i);
    }
}
  • 자바제어자 : public, protected,default, private 와 같은 접근제어자 static 또는 final, abstract 일반제어자의 제어자가 올 수 있습니다.
    접근제어자의 경우 필수로 하나 입력해줘야하며, 나머지 제어자는 필요할 경우 입력해줍니다.
    입력 순서 : 접근제어자 > static > 일반제어자 순으로 작성합니다.

    💡 전 메서드 작성하면서 접근제어자를 입력한적이 없는걸요?
    접근제어자를 미입력 시 자바 자체에서 default로 해석하게됩니다. 따라서 접근제어자가 입력되지 않은 메서드는 default접근 제어자를 갖고있다고 보면 됩니다.

  • 리턴타입 : 해당 함수의 리턴값이 있다면 해당 리턴값의 자료형을 적어주고, 없을 경우 void로 작성합니다.

    💡 리턴 타입이 없는void에서의 return
    void타입의 경우 해당 메서드가 return되는 값이 없음을 의미합니다. 그런데 간혹 void로 선언된 메서드 내부에 return 키워드가 보이곤 합니다. 이 때의 return은 해당 메서드를 종료하는 키워드로써 동작합니다.

  • 메서드명 : 메서드명은 변수명 네이밍규칙과 동일합니다. 관습적으로 영문 소문자로 시작합니다.

  • 매개변수 : 해당 메서드 사용시 입력받을 매개변수명을 입력해주고 변수를 선언할 때와 마찬가지로 자료형도 함께 작성해야합니다. 매개변수는 여러개 입력할 수 있으며 ,(쉼표)로 구분해줍니다.
    입력예시 : void play(int a) {...}, void play(int a, int b, double c) {...}

    💡 가변 길이 배열 입력매개변수
    메서드를 생성할 때 매개변수를 받긴 받아야하는데....몇개가 들어올지는 모르는 상황에서 사용할 수 있습니다.

    //사용법
    자바제어자 리턴타입 메서드명 (자료형...변수명) {
    	메서드 내용;
    }
    //사용예시
    void play(int...a) {
    	메서드 내용;
    }

    이렇게 입력된 메서드를 실제 사용시 사용될 때 입력된 변수들이 배열로 저장되어 해당 배열을 이용하는 메서드 내용을 구현할 수 있습니다.

  • 메서드 시그니처
    메서드는 위 자바제어자, 리턴타입, 메서드명, 매개변수로 구성되어있습니다.
    이러한 구성요소 가운데서 해당 함수 구분하는 기준을 메서드 시그니처 라고 하며, 메서드명, 매개변수가 그 기준이 됩니다.

    void play() {...}
    void play(int a) {...}
    void play(double b) {...}
    void play(int a, int b) {...}

    위 3개의 메서드의 경우 모두 이름이 play지만 매개변수의 개수와 자료형이 다르므로 전부 다 다른 함수라고 할 수 있습니다.

    이런식으로 메서드 시그니처를 달리하여 동일한 함수명으로 여러개의 함수를 정의하는 것오버로드라고 합니다.
    결국 오버로드란 함수의 중복정의를 말합니다!!

생성자

객체를 생성하는 역할을 하며 필드의 초기화 또한 생성자 내에서 수행하게끔 합니다.

생성자는 작성할 때는, 아래의 규칙을 지켜야합니다.
1. 반드시 클래스명과 동일한 이름으로 지어야합니다.
2. 생성자는 메서드와 비슷한 생김새를 지니고있지만 리턴 타입이 없습니다.

class A {
	A() {...} //생성자
}

생성자는 위처럼 클래스명과 동일한 이름을 갖고 클래스명() {내용} 형태를 갖습니다. 메서드와 마찬가지로 매개변수를 받을 수 있고, 중괄호 안에 실행 내용을 작성할 수 있습니다.

  • 기본 생성자 : 클래스명() { } 의 형태로 매개변수도, 내용도 없는 형태 입니다.

이러한 생성자는 사용자가 직접 클래스 내부에 작성할 수도 있지만, 작성하지 않을 경우 자바 자체에서 컴파일러가 자동으로 기본생성자를 만들어 줍니다.

다만, 사용자가 직접 생성자를 작성하게되면 컴파일러는 기본생성자를 만들지 않으므로, 기본 생성자를 직접 작성 후 사용자 정의 생성자를 작성하는 방식이 옳습니다.

💡 잠깐! 기본생성자? 사용자 정의 생성자?
기본 생성자는 말그대로 해당 클래스에 대한 인스턴스 생성만이 목적인 생성자로, 매개변수도, 내용도 없는 생성자입니다.
사용자 정의 생성자는 사용자가 필요에 의해 매개변수를 받거나, 필드 초기화 등을 생성자 관련 코드를 작성해주는 경우 등 사용자가 직접 정의하는 생성자입니다.

class A {
	int a;
	int b;
	A() {};                 // 기본 생성자
    A(int d, int e) {       // 사용자 정의 생성자
    	a = d;
        b = e;
    }
}

이런식으로 클래스 내부에는 생성자가 여러개 있을 수 있으며, 이는 생성자 또한 오버로드가 가능하기 때문입니다.

this, this()

클래스 내부에서 멤버요소(필드, 메서드, 이너클래스)를 호출하기 위해서는 this라는 참조변수 또는 this() 메서드를 이용할 수 있습니다.

  • this : 자신이 포함된 클래스의 객체를 가르키는 키워드 입니다. 포인트 연산자로 내부 필드에 접근할 수 있습니다.
  • this() : 생성자 내부에서 자신이 포함된 클래스의 다른 생성자를 호출하는 키워드입니다.
    1. 생성자의 내부에서만 사용할 수 있습니다.
    2. 생성자의 첫 줄에 위치해야합니다.
class A {
    String a = "안녕하세요!";
    void printHello(int a) {
        System.out.println(this.a);
        System.out.println(a + "번째 방문입니다.");
    }

    A() {
        System.out.println("첫번째 생성자!");
    }
    A(int a) {
        this();
        System.out.println("두번째 생성자!");
    }
}

public class Main {
    public static void main(String[] args) {
        A a1 = new A();
        System.out.println();
        A a2 = new A(1);
        System.out.println();

        a1.printHello(2);
        System.out.println();
        a2.printHello(3);
    }
}

클래스의 외부 구성요소

클래스 외부의 구성요소입니다. 패키지, 임포트 , 외부 클래스가 있습니다.

패키지

패키지란 비슷한 목적으로 생성된 클래스 파일들을 한곳에 모아 둔 일종의 폴더 개념으로 볼 수 있습니다.
패키지를 지정하지 않을 시 디폴트 패키지(현재 프로젝트 소스폴더 바로 밑에)로 설정 됩니다.

패키지를 사용하는 이유는,
1. 클래스 파일을 목적별로 관리하기 위함
2. 패키지마다 이름공간을 생성해줌으로써 클래스 간의 이름 충돌 발생 방지
(동일한 클래스명으로 작성된 경우 패키지가 분리될 경우 충돌이 발생하지 않습니다.)

package first.second;

public class Main {
	...
}

패키지를 설정한 경우에는 반드시 파일 최상단(주석제외) 패키지 선언부를 작성해줘야합니다.

임포트

다른 패키지 내의 클래스를 사용하기 위해서는 2가지 방법이 있습니다.

1. 클래스의 풀네임 사용
패키지명.클래스명으로 사용하는 방법입니다.
별다른 임포트 없이 바로 코드에서 사용할 수 있습니다.
다만, 패키지명까지 전부 입력하는 방식이어서 1회성으로 사용할 때는 괜찮지만 여러번 사용해야할 때는 번거로움이 있습니다.

2. 임포트 사용
import 패키지명.클래스명로 다른 패키지의 클래스를 가져와서 사용할 수 있습니다. 또는
임포트 해온 후로는 해당 클래스명을 이용해서 사용하면 됩니다.

import 패키지명.클래스명; // 다른 패키지의 특정 클래스 임포트
import 패키지명.*;      // 다른 패키지의 클래스 전체 임포트 (다만 하위폴더는 임포트 X)

위 2가지 방식을 적절히 혼용하여 사용할 수 있습니다.

예를 들어 각 각 다른 패키지에 위치한 동일한 이름의 클래스는 임포트 방식으로 둘다 가져올 수는 없습니다. 하나는 임포트해오고 다른 하나는 풀네임으로 사용하는 방식을 사용해야합니다.

외부 클래스

외부 클래스란 해당 파일에서 public 클래스 외 작성된 클래스를 말합니다!

외부 클래스는 public 제어자가 붙을 수 없고 해당 패키지에서만 사용 가능한 default 상태이기 때문에 외부 패키지에서 임포트 해갈 수 없습니다.

class Sub {
	//나는 외부 클래스~~ 같은 패키지 안에서만 사용할 수 있지! 파일명과 내이름은 무상관이지
}

public class Main {
	//나는야 이 파일의 유일한 public 클래스~ 파일명도 내 이름과 같지
}

객체 생성과 활용

클래스는 그 자체로 사용할 수 없으며, 객체를 생성해서 그 안에 설계되어있는 필드, 메서드, 이너 클래스 등을 사용해야합니다.
그래서 클래스란 객체를 생성하기 위한 설계도 또는 청사진이라고 말하고는 합니다.

클래스로 객체를 만드는 과정을 인스턴스화라고 하며 이렇게 만들어진 객체를 인스턴스라고 합니다.

객체 생성

클래스명 변수명 = new 생성자();

인스턴스(객체)를 생성할 수 있습니다.
위 형식의 경우 참조자료형 변수 선언에서도 볼 수 있었는데, 클래스도 참조자료형이기 때문에 동일한 형식을 사용합니다.

객체 생성

클래스명(자료형)인 변수에 A() 생성자로 만들어진 객체를 new키워드로 힙 메모리에 할당하고 그 주소를 변수 a에 저장하는 방식입니다.

객체 접근

객체를 생성 후 객체 내 메서드 또는 필드 접근할 수 있습니다.
접근하는 방법으로는 포인트 연산자를 이용할 수 있습니다.

//사용법
변수명(객체).필드명;
변수명(객체).메서드명();

//사용예시
A a = new A();
a.name;
a.sayhello();

참고

Do it! 진짜 개발자가 되는 Java 프로그램 입분서 자바 완전 정복 - 김동형
위 책을 공부하며 작성하고 있습니다!

profile
개발자를 꿈꾸는 병아리 (블로그 이전 준비중 입니다.)

0개의 댓글