클래스를 패키지에 종속시키려면 클래스 선언전에 package 키워드를 이용해 어떤 패키지에 속해있는지 정해줘야한다. 만약 정해주지 않는다면, 클래스는 기본적으로 "default package"에 속하게 되고 "default package"는 아무런 패키지 이름을 가지지 않는다. 그리고 해당 클래스를 파일 디렉토리상으로도 패키지 구조와 일치하게 이동해야 한다. 

 

답 : System class는 JDK 와 Eclipse에 기본적으로 제공되는 패키지인 default package에 속하게 되고 "default package"는 아무런 패키지 이름을 가지지 않는다. 따라서 import java.lang*을 추가해주어도(package를 추가해 주어도) 똑같은 결과를 나타낸다. 또한 이러한 System 클래스는 java.lang 패키지에 포함되어 제공된다.

 


질문 : 위의 프로그램은 패키지 이름이 없다. 프로그램의 소스파일이 어떤 패키지에 저장되어 있는가?

답 : java.lang


질문 : 위의 프로그램은 constructor가 없다. 컴파일러는 default constructor을 프로그램에 자동으로 추가한다. 컴파일러에 자동적으로 추가된 default constructor의 코드를 써라.

 

풀이 : default 생성자는 컴파일러가 제공하는 기본 생성자이다. 기본 생성자는 매개변수도 없고 로직의 내용도 없다. 따라서 아무 기능도 없다.

답 : Welcome1() {};


질문 : 위의 프로그램을 쓰고 come.java 라는 이름으로 저장해라. 너가 프로그램을 돌렸을 때 에러가 나는가? 왜 그런가?

답 : 에러가 난다. public으로 선언된 클래스가 있다면 반드시 그 클래스명과 파일명이 같아야 한다. 한 파일 내에 클래스가 여러 개 있을 수 있는데, public class는 하나만 존재할 수 있으며, 파일명과 같아야 합니다.


질문 : public 키워드를 지워라. 프로그램을 돌렸을 때 똑같은 이름을 얻을 것이다. 어떤 종류의 access modifier가 쓰였는가?

답 : default


자바에서 패키지(Package)란 클래스들의 모음이다. 패키지를 통해 편리하게 프로젝트를 관리할 수 있고 내 코드들을 다른 라이브러리로부터, 또 다른 라이브러리들끼리 서로 구분가능하다. 기본적인 자바 라이브러리 또한 java.lang, java.util. java.net java.awt와 같은 다양한 패키지들를 통해 분류된다. 자바 라이브러리는 우리가 일반 폴더 구조에서 볼수있는 계층적 패키지구조를 가지고 있다. 상위 패키지에 하위패키지가 종속되는 형식이다. 그래서 모든 자바 패키지들은 가장 상위 패키지인 java와 javax 패키지에 종속되어 있다. 

패키지(Package)를 사용하는 가장 큰 이유는 클래스명의 고유성을 보장하기 위해서이다. 만약 다른 두 프로그래머가 서로 다른 목적을 가진 클래스를 생성했는데 이름 같다 가정할 때, 서로 다른 패키지를 사용함으로써 충돌을 피할수 있다. 그리고 패키지 이름의 고유성을 보장하기 위해 최상위 패키지명에 "com.muckycode"와 같은 방식으로 인터넷 도메인 주소를 꺼꾸로 사용하기도 한다. 인터넷 도메인은 이미 고유성을 가지고 있기때문에 다른 충돌을 걱정할 필요가 없기 때문이다. 

클래스는 같은 패키지내 모든 클래스들과 다른 패키지내 모든 public 클래스들을 사용할수있다. 다른 클래스를 사용하는데는 2가지 방법이 있다. 
하나는 클래스 선언전 import 키워들 이용해서 패키지 전부 또는 클래스 1개만을 가져와 사용하는것과, 패키지 전체 주소를 가져와 사용하는것이다.

위방식은 클래스 사용시마다 매번 주소를 입력해야되기 때문에 엄청 귀찮다. 그래서 보통은 import 방식을 쓰게된다.

import 방식은 하나의 클래스에만 적용가능하지만, * 문자를 이용해서 패키지의 모든 하위 클래스에도 적용이 가능하다. 
import 방식을 이용하는것은 편리하지만, 만약 서로 다른 패키지가 같은 이름을 가진 클래스를 가지고 있다면 이는 컴파일시 에러로 이어진다. 컴파일러가 무슨 클래스를 로드해야될지 모르기 때문인데, 이를 피할려면 특정 클래스의 주소를 import하는 방식을 사용해야한다. 만약 같은 이름을 가진 클래스들을 모두 사용해야한다면 패키지 전체 주소를 이용하는 방식을 사용해야한다. 예를들면 Date라는 클래스는 java.util 패키지에도 존재하고, java.sql 패키지에도 존재한다. 두 패키지를 모두 사용한다는 가정하에 import 방식을 이용하면 

위와 같은 컴파일 에러를 얻게된다. 그래서 이럴때는 import 방식 말고 전체 주소를 이용하는 방식을 이용해야한다.

import 방식은 static 클래스, 메소드, 데이터 필드들도 적용이 가능하다. 
자주쓰는 System.out 객체는 static 클래스인 System을 import 하거나, static 객체인 System.out을 import하여 간소화할수 있다.

위 클래스는 com.muckycode.java.app 패키지에 속하게 되고, com폴더 -> muckycode폴더 -> java폴더 -> app폴더 내에 존재해야한다.

클래스를 패키지에 종속시키려면 클래스 선언전에 package 키워드를 이용해 어떤 패키지에 속해있는지 정해줘야한다. 만약 정해주지 않는다면, 클래스는 기본적으로 "default package"에 속하게 되고 "default package"는 아무런 패키지 이름을 가지지 않는다. 그리고 해당 클래스를 파일 디렉토리상으로도 패키지 구조와 일치하게 이동해야 한다. 


Constructor : 생성자

생성자의 이름은 클레스 이름과 같아야 한다.

생성자는 명시적 return 타입이 없어야 한다.

만약 클래스에 생성자가 없다면, 컴파일러는 자동적으로 초기 생성자를 만든다.

초기 생성자는 객체에 0,null과 같은 초기값을 제공한다.

Default 생성자

컴파일러가 제공하는 기본 생성자.

클래스이름 () { }
Card() { }

 

기본 생성자는 매개변수도 없고 로직의 내용도 없다.

 

Data 1의 인스턴스 : 에러발생 (X)

Data 2의 인스턴스 : 에러발생 (O)

 

Data 1 클래스 내에 생성자가 없으므로 컴파일러가 "기본 생성자"를 추가해준다.

(기본생성자가 컴파일러에 의해서 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을 때)

 

Data2 클래스 내에 생성자 Data2 (int x) { Value = x ; } 가 정의되어 있다.

Date2 생성자를 살펴보면 매개변수로 int x가 전달되고 있다. (즉, 매개변수가 있는 생성자)

(그런데,  컴파일러는 매개변수가 있는 생성자가 있을 때는 자동으로 기본생성자를 만들어주지 않음)

 

따라서 위 에러를 고치는 두 가지 방법이 있다.

1. Data 2 클래스 내에 기본 생성자(default constructor)를 만들어주거나

2. 인스턴스 생성할 때 int 타입의 정수를 던져주거나

 

 

class Data2 내에 Data2() {} ; 를 추가해주거나

Data2 인스턴스를 생성할 때 생성자 Data2(임의의 정수값)을 사용하면 된다.


접근제어자 (Access Modifier)

자바에는 다음과 같은 접근 제어자가 있다.

  1. private
  2. default
  3. protected
  4. public

private -> default -> protected -> public 순으로 보다 많은 접근을 허용한다.

1. private

접근제어자가 private으로 설정되었다면 private 이 붙은 변수, 메소드는 해당 클래스에서만 접근이 가능하다.

public class AccessModifier {
    private String secret;
    private String getSecret() {
        return this.secret;
    }
}

위 예제의 secret 변수와 getSecret 메소드는 오직 AccessModifier 클래스에서만 접근이 가능하고 다른 클래스에서는 접근이 불가능하다.

2. default

접근제어자를 별도로 설정하지 않는다면 접근제어자가 없는 변수, 메소드는 default 접근제어자가 되어 해당 패키지 내에서만 접근이 가능하다.

 

아래 코드를 보자.

 

HouseKim.java

package jump2java.house;

public class HouseKim {
    String lastname = "kim";
}

HousePark.java

package jump2java.house;

public class HousePark {
    String lastname = "park";

    public static void main(String[] args) {
        HouseKim kim = new HouseKim();
        System.out.println(kim.lastname);
    }
}

HouseKim과 HousePark의 패키지는 jump2java.house로 동일하다. HouseKim의 lastname 변수는 접근제어자가 default이므로 HousePark 클래스에서 main 메소드에서 사용한 것과 같이 kim.lastname 으로 HouseKim의 lastname 변수에 접근이 가능하다.

3. protected

접근제어자가 protected로 설정되었다면 protected가 붙은 변수, 메소드는 동일 패키지내의 클래스 또는 해당 클래스를 상속받은 외부 패키지의 클래스에서 접근이 가능하다.

 

다음의 예를 보자.

 

HousePark.java

package jump2java.house;

public class HousePark {
    protected String lastname = "park";
}

EungYongPark.java

package jump2java.house.person;

import house.HousePark;

public class EungYongPark extends HousePark {       
    public static void main(String[] args) {
        EungYongPark eyp = new EungYongPark();
        System.out.println(eyp.lastname);       
    }    
}

HousePark클래스를 상속받은 EungYongPark이라는 클래스의 패키지는 jump2java.house.person으로 HousePark의 패키지인 jump2java.house와 다르지만 HousePark의 lastname 변수가 protected로 설정되었기 때문에 eyp.lastname과 같은 접근이 가능하다. 

 

만약 lastname의 접근제어자가 protected 가 아닌 default 접근제어자였다면 eyp.lastname 문장은 컴파일 에러를 유발 할 것이다.

4. public

접근제어자가 public으로 설정되었다면 public 접근제어자가 붙은 변수, 메소드는 어떤 클래스에서라도 접근이 가능하다.

package jump2java.house;

public class HousePark {
    protected String lastname = "park";
    public String info = "this is public message.";
}

위 예제의 HousePark의 info 변수는 public 접근제어자가 붙어 있으므로 어떤 클래스에서던지 접근이 가능하다.

 

이상과 같이 총 4개의 접근제어자에 대해서 알아보았다.

예제는 변수만을 대상으로 설명했지만 메소드도 마찬가지의 접근제어 규칙을 따른다.

'📌 java > Object-oriented Programming' 카테고리의 다른 글

java - txt.file  (0) 2020.03.26
java.util.Arrays - Arrays 클래스  (0) 2020.03.26
java.util.Scanner  (0) 2020.03.25
Homework_W2-01  (0) 2020.03.25
Homework_02  (0) 2020.03.20
복사했습니다!