패키지

자바에서 패키지(package)는 디렉터리의 개념과 동일하다. 따라서 패키지를 이용하면 비슷한 기능의 클래스들을 같은 디렉터리로 묶어서 관리할 수 있다.

 

패키지 선언

 

패키지를 이용하면 연관된 클래스들을 하나의 디렉터리로 묶어서 관리할 수 있다. 그런데 사실 이런 패키지의 가장 근본적인 용도는 동일한 이름의 클래스를 다른 용도로 사용하기 위함이다.

 

예를 들어 현재 작업 중인 디렉터리에 학생 클래스에 해당하는 Student.java 파일이 존재하는데, 이 Student 말고 다른 용도의 Student 클래스를 작성한다고 가정해보자. 당연히 디렉터리에 두 개의 Student.java 파일이 존재할 수 없으므로 문제가 생길 것이다. 자바에서는 이런 경우 패키지를 통해 클래스를 분리한다.

 

클래스에 패키지를 선언할 때는 package라는 예약어를 사용한다.

package 패키지경로;

패키지 선언은 주석을 제외하고 반드시 클래스 파일의 가장 첫 번째 줄에 위치해야 한다.

패키지가 여러 개의 디렉터리로 구성되어 있는 경우, 패키지 경로를 점(.)을 이용하여 구분하되 관례상 소문자로만 구성한다.

 

현재 대학생의 시험 결과만 관리하던 프로그램에서 고등학생의 성적을 추가로 관리한다고 가정하자. 그런데 현재 프로젝트에 고등학생에 해당하는 Student 클래스를 작성하려고 하면 이미 Student 클래스가 존재한다는 경고 메시지가 출력될 것이다.

 

이때 shcool.high 라는 패키지를 지정하면 경고는 사라지고 정상적으로 Student 클래스를 생성할 수 있게 된다.

패키지는 물리적으로 디렉터리이기 때문에 클래스에 패키지를 선언하면 패키지에 해당하는 디렉터리들이 만들어진다. 따라서 school/high 디렉터리에 Student.java 파일이 위치한 것을 확인할 수 있다.

 

 

 

728x90

'Language > JAVA' 카테고리의 다른 글

[JAVA] 테스트코드 작성하기  (1) 2023.10.24
[JAVA] 메소드 Method  (0) 2023.10.19
[JAVA] 접근 제어자  (0) 2023.10.19
[JAVA] 클래스 Class (3)  (0) 2023.10.18
[JAVA] 클래스 Class (2)  (0) 2023.10.18

접근 제어 개념

객체에 포함된 멤버 변수 중에는 중요한 변수와 별로 중요하지 않은 변수가 있다. 예를 들어 Student 객체의 이름(name)은 외부에 공개해도 상관없지만 점수(score)를 공개하는 것은 문제가 될 수 있다. 이렇게 외부에 공개할 정보와 그렇지 않은 정보를 구분하여 외부로부터의 접근을 제어하기 위해 접근 제어를 사용하는 것이다.

 

접근 제어와 관련한 예약어 중에서 public은 해당 요소(클래스, 멤버 변수, 메소드)에 대한 모든 접근을 허용한다는 의미이며, 반대로 private은 모든 접근을 차단한다는 의미이다.

 

간단한 예제를 통해 public과 private의 의미를 확인해볼 것이다.

// 1. 클래스 선언부
public class Student {
	
    // 2. 멤버 변수
    public String name = "둘리";
    private int score = 83;
    
    // 3. 생성자 메소드
    Student() {	
    	System.out.println("---> Student 객체 생성");
    }
    
    // 4. 멤버 메소드
    public void printInfo() {
    	System.out.println(name + "의 점수 : " + score);
    }
}

 

score는 private 멤버 변수라 접근할 수 없음으로 위 처럼 에러가 발생하고, name 멤버 변수는 public 변수이기 때문에 접근이 가능하다.

Student 클래스의 생성자를 private으로 바꾸는 순간 Student클래스로부터 객체를 생성하는 모든 소스에 문제가 발생하게 된다. 이는 외부 클래스에서 Student 클래스의 생성자에 접근할 수 없게 되었기 때문이다.

 

물론 디자인 패턴 중에서 싱글톤 패턴(Singleton Pattern)같은 아주 특수한 상황에서 가끔 private 생성자를 사용하기도 한다. 하지만 이는 정말 특수한 경우이고 일반적으로는 생성자 앞에 private을 설정하지 않는다.

 

접근 제한과 관련된 예약어 중에는 protected와 default라는 것도 있다. 이 중에서 protected는 상속과 관련된 접근 제한 예약어로서 프로그램의 가독성을 떨어뜨리기 때문에 거의 사용하지 않는다. default는 패키지와 관련된 접근 제한이다.

728x90

'Language > JAVA' 카테고리의 다른 글

[JAVA] 메소드 Method  (0) 2023.10.19
[JAVA] 패키지  (0) 2023.10.19
[JAVA] 클래스 Class (3)  (0) 2023.10.18
[JAVA] 클래스 Class (2)  (0) 2023.10.18
[JAVA] 클래스 Class (1)  (0) 2023.10.18

객체의 생성

클래스로부터 객체를 생성하기 위해서는 new라는 예약어를 사용해야 한다. new는 객체 생성 연산자이다. 

new 생성자();

다음은 Student 클래스로부터 객체를 생성하는 과정이다.

public class Student {
	String name;
    int score;
}


new Student();

 클래스로부터 객체를 생성할 때 생성자가 자동으로 호출되는데, 이때 클래스의 멤버 변수가 초기화된다. 클래스로부터 객체를 생성하는 것은 배열 객체를 생성하는 것과 비슷하다. 다만 배열은 동일한 타입의 데이터만 저장할 수 있지만, 클래스는 다른 타입의 데이터도 저장할 수 있다. 이는 클래스에 선언된 멤버 변수들의 타입이 다르기 때문이다.

 

객체의 사용

클래스로부터 생성된 객체는 배열과 동일하게 참조 변수를 통해서만 접근할 수 있다. 참조 변수에 생성된 객체의 주소를 할당하는 과정은 다음과 같다.

클래스이름 참조변수;
참조변수 = new 생성자();

// 예시
Student kim;
kim = new Student();

Student lee = new Student();

 

이제 kim이라는 참조 변수를 통해서 메모리에 생성된 Student 객체에 접근할 수 있고, Student 객체에 포함된 멤버 변수를 사용할 수 있다. 

 

public class StudentTest {
    public static void main(String[] args) {
        Student kim = new Student();
        kim.name = "둘리";
        kim.score = 83;
        
        System.out.println("이름 : "+kim.name); // 둘리
        System.out.println("성적 : "+kim.score); // 83
    }
}


class Student {
    String name;
    int score;
}

먼저 생성자를 통해 Student 클래스의 객체를 생성했다. 그리고 kim 이라는 참조 변수를 통해 Student 객체에 포함된 name과 score 변수에 각각 "둘리", 83 이라는 값을 할당했다. 그리고 나서 Student 객체가 가진 name, score 변수의 값을 출력했다.

 

728x90

'Language > JAVA' 카테고리의 다른 글

[JAVA] 패키지  (0) 2023.10.19
[JAVA] 접근 제어자  (0) 2023.10.19
[JAVA] 클래스 Class (2)  (0) 2023.10.18
[JAVA] 클래스 Class (1)  (0) 2023.10.18
[JAVA] 버블 정렬 알고리즘  (0) 2023.10.18

클래스

클래스는 현실 세계의 객체를 추상화하여 소스 코드 형태로 만든 결과물이며, 자바 프로그램의 가장 기본이다. 이런 클래스의 구조와 문법에 대해서 구체적으로 살펴보자.

 

클래스의 구조

클래스는 class 라는 예약어를 사용하여 선언하며, 클래스의 일반적인 구조는 다음과 같다.

// 클래스 선언부
class 클래스 이름 {
	// 멤버 변수 선언
    
    // 생성자 메소드 선언
    
    // 메소드 선언
}

먼저 class 라는 예약어 뒤에 클래스 이름이 온다. 그리고 클래스 이름 뒤에는 클래스에 대한 시작 블록이 등록하고, 이 블록 안쪽에 클래스의 구성 요소들이 선언된다.

 

클래스는 멤버 변수, 생성자 메소드 그리고 일반 메소드로 구성되며, 각 요소의 순서는 바뀔 수 있다. 즉, 멤버 변수가 맨 아래 선언돼도 상관없다는 의미다. 하지만 일반적으로는 위 순서대로 작성하는 것이 가독성 측면에서 바람직하다.

 

위와 같은 구조로 학생에 해당하는 Student 클래스를 작성한다면 다음과 같은 형태가 될 것이다.

//  1. 클래스 선언
class Student {
    // 2. 멤버 변수 선언
    String name;
    int score;
    
    // 3. 생성자 메소드
    Student() {
        System.out.println("---> Student 객체 생성");
    }
    
    // 4. 메소드
    void printInfo() {
        System.out.println(name + "의 점수 : "+ score);
    }



}

 

자바는 하나의 파일에 하나의 클래스를 작성하는 것을 원칙으로 한다. 가끔 테스트를 목적으로 하나의 파일에 여러 클래스를 작성하기도 하지만, 이런 경우 public 예약어가 붙은 클래스는 하나만 지정할 수 있다. 그리고 반드시 다음과 같이 public 예약어가 붙은 클래스를 파일 이름으로 지정해야 한다.

public class MainClass {
	
}

class subClass {
}

 하나의 파일에 여러 클래스를 작성한 경우, 자바 파일은 MainClass.java 로 하나지만 컴파일 결과로 만들어진 .class 파일은 클래스 수 만큼 만들어진다.

즉 위 코드를 컴파일하면 MainClass.class, subClass.class 두개의 클래스가 만들어진다.

 

클래스 선언부

클래스 선언부에는 가장 먼저 class 라는 예약어가 등장한다. class는 지금부터 새로운 클래스가 정의된다는 것을 JVM에게 알려준다. class 예약어 뒤에 나오는 Student 가 클래스 이름이며, 클래스 이름은 대문자로 시작한다는 것만 제외하면 변수 이름 규칙과 동일한 규칙을 적용받는다.

 

멤버 변수

클래스 선언부 바로 밑에는 가장 먼저 멤버 변수가 등장한다. 멤버 변수는 클래스에 속한 변수라고 하여 '클래스 변수' 또는 '필드' 라고 하는데, 우리는 이후에 진행되는 모든 설명과 실습에서 멤버 변수로 통일하여 부를 것이다.

 

멤버 변수는 우리가 알고 있는 일반 변수와 동일하다. 다만 지금까지 사용했던 변수가 main()이라는 특수한 메소드 안에서만 선언되고 사용됐던 로컬 변수라면, 멤버 변수는 main() 메소드가 아닌 다른 메소드에서도 사용할 수 있는 글로벌 변수이다. 심지어 다른 클래스에서도 사용할 수 있다.

 

래스에서 멤버변수가 중요한 이유는 클래스로부터 객체가 생서될 때 객체에 포함되는 유일한 요소이기 때문이다. 즉, 클래스로부터 생성된 객체는 생성자 메소드나 일반 메소드는 포함하지 않고 오직 멤버 메소드만 포함한다.

 

우리가 프로그램에서 객체를 이용한다는 것은 결국 멤버 변수에 할당된 데이터를 이용한다는 것을 의미한다. 또한 클래스에 포함된 생성자나 메소드는 모두 멤버 변수를 위해 존재한다.

 

생성자 메소드

멤버 변수 다음에 등장하는 것이 생성자(constructor)메소드다. 생성자 라고도 부른다. 생성자는 클래스 이름과 동일한 이름을 가지고 있으며, 기능적으로는 멤버 변수의 초기화를 담당한다. 

생성자 역시 큰 범위에서 보면 메소드에 해당하기 떄문에 누군가에 의해 호출되어야만 한다. 생성자가 호출되는 시점은 클래스로부터 객체(인스턴스)를 생성할 때다. 즉, 생성자를 통해 클래스로부터 객체를 생성할 수 있으며, 이때 객체에 포함되는 멤버변수 초깃값을 갖게 된다. 

 

메소드

클래스 마지막에 선언된 것이 메소드인데, 메소드를 함수(function)와 동일한 개념으로 이해하면 쉽다. 즉, 메소드는 객체가 제공하는 동사적 특징인 기능이다. 클래스에 선언된 메소드를 실행하기 위해서는 우선 메소드가 포함된 클래스의 객체가 생성되어야 한다. 그래야 객체를 참조하는 참조변수를 통해서 메소드를 호출할 수 있다.

 

대부분의 메소드는 메소드 이름에 해당하는 기능을 제공하며, 메소드에 포함된 기능이 실행되기 위해서는 데이터가 필요하다. 이런 데이터는 메버 변수에 할당된 데이터를 이용할 수도 있지만, 매개변수를 통해 전달된 데이터를 이용할 수도 있다. 

728x90

'Language > JAVA' 카테고리의 다른 글

[JAVA] 접근 제어자  (0) 2023.10.19
[JAVA] 클래스 Class (3)  (0) 2023.10.18
[JAVA] 클래스 Class (1)  (0) 2023.10.18
[JAVA] 버블 정렬 알고리즘  (0) 2023.10.18
[JAVA] 참조 변수와 null  (0) 2023.10.18

+ Recent posts