0. 학습할 것
- package 키워드
- import 키워드
- 클래스패스
- CLASSPATH 환경변수
- -classpath 옵션
- 접근지시자
1. package 키워드
클래스와 인터페이스의 집합을 의미한다.
이렇게 서로 관련이 있는 클래스나 인터페이스를 함께 묶음으로써 파일을 효율적으로 관리할 수 있게 된다.
자바에서 패키지는 물리적으로 하나의 디렉터리를 의미한다.
하나의 패키지에 속한 클래스, 인터페이스 파일은 모두 해당 패키지 이름의 디렉터리에 포함되어 있다.
이러한 패키지는 다른 패키지를 포함할 수 있으며, 이때 디렉터리의 계층 구조는 점(.)으로 구분된다.
상위패키지.하위패키지.클래스
패키지는 클래스를 유일하게 만들어주는 "식별자" 역할을 한다.
클래스의 전체 이름은 "패키지 + 클래스명" 이다.
모든 클래스에는 정의된 클래스 이름과 패키지 이름이 있다. 이 둘을 합쳐야 완전하게 한 클래스를 표현한다고 할 수 있으며 FQCN(Fully Qualified Class Name) 이라고 한다.
클래스는 다음과 같이 선언한다.
package 상위패키지.하위패키지;
public class ClassName{ ... }
패키지 네이밍 규칙은 다음과 같다.
- 숫자로 시작해서 안된다.
- _, $ 를 제외한 특수문자를 사용해서는 안된다.
- java로 시작하는 패키지는 자바 표준 api 에서만 사용하므로 사용해서는 안된다.
- 모두 소문자로 작성하는 것이 관례이다.
- 자바의 예약어를 사용하면 안된다.
빌트-인 패키지(Built-in package)
다운로드한 JDK 또는 JRD와 함께 제공되는 패키지를 빌트-인 패키지 라고 한다.
빌트-인 패키지는 JAR 파일의 형태로 제공되며 JAR 파일의 압축을 풀면 JAR 파일의 패키지(예: lang, io, util, SQL 등)를 쉽게 볼 수 있다.
가장 자주 쓰이는 패키지로는 java.lang과 java.util이 있다.
java.lang은 자주 사용하는 패키지이지만 한번도 import하여 사용한적이 없다.
즉, 자바에서 java.lang 패키지는 기본적으로 제공하는 것들이므로 import로 불러오지 않아도 자바가 알아서 java.lang의 클래스를 불러온다.
2. import 키워드
Import 키워드는 다른 패키지에 있는 클래스를 불러오기 위해서 사용하는 키워드이다
다른 패키지의 클래스를 사용하려면 패키지명이 포함된 클래스 이름을 사용해야 한다.
하지만, 매번 패키지명을 붙여서 작성하긴 쉽지 않다.
클래스의 코드를 작성하기 전에 import 문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명은 생략할 수 있다.
컴파일 시에 컴파일러는 import문을 통해 소스파일에 사용된 클래스들의 패키지를 알아 낸 다음, 모든 클래스 이름 앞에 패키지명을 붙여준다.
import 패키지명.클래스명;
또는
import 패키지명.*;
EX)
만약 다음과 같이 다른 이름의 패키지 같은 이름의 클래스를 호출하게 된다면 어떻게 될가?
package importTest;
public class mainTestClass {
private String name;
public mainTestClass (String name){
this.name = name;
}
public void printName(){
System.out.println("mainTest의 이름은 : " +name +" 입니다 ");
}
public void bPackage(){
SubPackageClass subPackageClass = new SubPackageClass("subpackage의 클래스");
subPackageClass.printName();
}
}
mainTestClass에서 SubPackageClass를 호출하려고 한다. 하지만 컴파일 에러가 발생하낟.
mainTestClass에서 어떤 SubPackageClass를 사용해야하는지 알 수 없고, SubPackageClass의 경로 파악이 안되기 때문이다.
그래서 사용하려는 Class가 어디에 있는지 클래스인지 경로를 알려줘야 한다.
3. 클래스패스
클래스를 찾기 위한 경로.
자바 가상 머신은 프로그램의 실행과정에서 실행에 필요한 클래스를 찾을때, 바로 이 클래스 패스를 기준으로 찾게된다.
자바프로그램의 실행과정을 다시 생각해보자
- 프로그램이 실행되면, JVM은 이 프로그램이 필요로하는 메모리를 할당받는다.
- 자바 컴파일러는 자바 코드를 자바 바이트코드로 변환한다. (클래스 > 바이트코드)
- class Loader를 통해 class 파일을 JVM에 로딩한다.
- 로딩된 classfile은 Execution Engine을 통해 해석된다. (인터프리터, JIT컴파일러)
- 해석된 바이트코드는 Runtime Data area에서 실질적으로 수행된다.
- 이러한 과정 속에서 JVM은 필요에 따라 Thread Synchronization과 GC같은 관리작업을 수행한다.
소스 코드(.java 파일)를 컴파일하면 소스 코드가 “바이트 코드”(바이너리 형태의 .class 파일)로 변환된다.
그리고
Class Loader 가 프로그램을 실행하기 위한 .class 파일들을 메모리에 적재시켜주는 역할을 한다.
BootStrap Class Loader
기본 클래스로더 중 최상위 클래스 로더로써,
jre/lib/rt.jar에 담긴 JDK 클래스 파일을 로딩 해준다.
String 클래스나, Object 클래스를 사용할 수 있었던 이유가 바로, BootStrap Class Loader 가 자동으로 메모리에 적재해주기 때문이다.
Extension Class Loader
익스텐션 클래스로더는 jre/lib/ext 폴더나 java.ext.dirs 환경 변수로 지정된 폴더에 있는 클래스 파일을 로딩한다.
Application Class Loader (System Class Loader)
바로 System Class Loader 가 우리가 만든 class 를 메모리에 올리는 역할을 하는데, 그 때, classpath 기준으로 클래스들을 로드해준다.
Java runtime(java 또는 jre)으로 이 .class 파일에 포함된 명령을 실행하려면, 먼저 이 파일을 찾을 수 있어야 한다.
이 때 .class 파일을 찾을 때 classpath에 지정된 경로를 사용한다.
classpath를 지정할 수 있는 두 가지 방법이 있다.
- 환경 변수 CLASSPATH를 사용하는 방법
- Java runtime 에 -classpath 옵션을 사용하는 방법
4. CLASSPATH 환경변수
컴퓨터 시스템 변수 설정을 통해 지정할 수 있다.
환경변수를 셋팅하지 않았을 경우
javac -version
이러한 오류를 호출하게 된다.
이는 운영체제에서 javac컴파일러에 대해 경로가 어디인지 파악을 못해서 발생하는 것이다.
이미지 출처 : https://github.com/dacapolife87/javaStudy/blob/main/study/week07/Week07_package.md
다음과 같이 환경변수를 셋팅하고
위의 명령어를 사용하면
환경변수가 셋팅된 것을 확인할 수 있다.
5. -classpath 옵션
클래스패스를 지정하는 방법은 실행할때 옵션을 주는 방법도 있다.
avac <options> <souce files>
컴파일러가 컴파일 하기 위해서 필요로 하는 참조할 클래스 파일들을 찾기 위해서
컴파일시 파일 경로를 지정해주는 옵션이다.
현재 디렉토리에서 하위 디렉토리 lib 에 있는 Hello.class 파일을 사용하려면 다음과 같이 할 수 있다.
java -classpath .:lib Hello
. 은 현재 디렉토리를 의미한다.
:은 경로와 경로를 구분하는 구분자 역할을 한다. (문자 사이의 ',' 같은 역할이라 생각하면 됩니다.)
.. 은 현재 디렉토리의 상위 디렉토리를 말한다.
6. 접근지시자
접근 지시자는 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 한다.
- 자바에서 정보은닉을 위해 접근 제어자라는 기능을 제공한다.
- 접근 제어자를 사용하면 클래스 외부에서의 직접적인 접근을 허용하지 않는 멤버를 설정하여 정보 은닉을 구체화할 수 있다.
- 접근 제어자는 해당 클래스 또는 멤버를 정해진 범위에서만 접근할 수 있도록 통제하는 역할을 한다
- 클래스는 public과 default밖에 쓸 수 없다.
정보 은닉(data hiding)이란 사용자가 굳이 알 필요가 없는 정보는 사용자로부터 숨겨야 한다는 개념.
사용자는 언제나 최소한의 정보만으로 프로그램을 손쉽게 사용할 수 있게 된다.
자바에서는 다음과 같은 네 가지의 접근 제어자를 제공한다.
1. private
2. public
3. default
4. protected
범위는 다음과 같다.
기타제어자
static
- static이 붙은 멤버변수와 메서드, 그리고 초기화 블럭은 인스턴스가 아닌 클래스에 관계된 것이기 때문에 인스턴스를 생성하지 않고도 사용할 수 있다.
- 인스턴스메서드와 static메서드의 근본적인 차이는 메서드 내에서 인스턴스 멤버를 사용하는가의 여부에 있다.
- static은 멤버변수, 메서드, 초기화 블럭에 사용될 수 있다.
제어자 | 대상 | 의미 |
static | 멤버변수 | - 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다. - 클래스 변수는 인스턴스를 생성하지 않고도 사용가능 - 클래스가 메모리에 로드될 때 생성 |
메서드 | - 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다. - static메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다. |
final
- 거의 모든 대상에 사용될 수 있다.
- 변수에 사용되면 값을 변경할 수 없는 상수가 되며, 메서드에 사용되면 오버라이딩을 할 수 없게 되고 클래스에 사용되면 자신을 확장하는 자손클래스를 정의하지 못하게 된다.
- final은 클래스, 메서드, 멤버변수, 지역변수에 사용할 수 있다.
제어자 | 대상 | 의미 |
final | 클래스 | 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다 그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다. |
메서드 | 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다. | |
멤버변수 | 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다. | |
지역변수 |
abstract
- 미완성의 의미를 가지고 있다.
- 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상메서드를 선언하는데 사용된다.
- abstract는 클래스, 메서드에 사용된다.
- 추상 클래스는 아직 완성되지 않은 메서드가 존재하는 '미완성 설계도' 이므로 인스턴스를 생성할 수 없다.
제어자 | 대상 | 의미 |
abstract | 클래스 | 클래스 내에 추상 메서드가 선언되어 있음을 의미 |
메서드 | 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다. |
제어자의 조합
자바에서는 접근 제어자와 기타 제어자를 한 대상에 함께 사용할 수 있다.
하지만 모든 경우가 가능한 것은 아니며, 대상에 따라 사용할 수 있는 조합은 아래와 같다.
대상 | 함께 사용할 수 있는 제어자 |
클래스 | public, (default), final, abstract |
메소드 | 모든 접근 제어자, final, static, abstract |
필드 | 모든 접근 제어자, final, static |
지역 변수 | final |
초기화 블록 | static |
또한, 자바에서는 제어자의 특성상 몇몇 제어자는 함께 사용할 수 없습니다.
1. 클래스에 final과 abstract는 함께 사용할 수 없습니다.
: final 제어자를 가지는 클래스는 다른 클래스가 상속받을 수 없게 되며, abstract 제어자를 가지는 클래스는 다른 클래스가 상속해서 오버라이딩해야만 사용할 수 있으므로, 이 두 제어자는 클래스에 함께 사용할 수 없습니다.
2. 메소드에 static과 abstract는 함께 사용할 수 없습니다.
: abstract 제어자를 가지는 메소드는 선언부만 있고 구현부가 없는 메소드인데, static 제어자를 가지는 메소드는 인스턴스를 생성하지 않고도 바로 사용할 수 있어야 하므로, 이 두 제어자는 메소드에 함께 사용할 수 없습니다.
3. 메소드에 private과 abstract는 함께 사용할 수 없습니다.
: abstract 제어자를 가지는 메소드는 다른 클래스가 상속하여 오버라이딩해야만 사용할 수 있는데, private 제어자를 가지는 메소드는 자식 클래스에서 접근할 수 없게 되므로, 이 두 제어자는 메소드에 함께 사용할 수 없습니다.
4. 메소드에 private과 final은 함께 사용할 필요가 없습니다.
: 메소드에 사용된 final 제어자와 private 제어자는 모두 해당 메소드가 오버라이딩을 통한 재정의를 할 수 없다는 의미를 가지므로, 둘 중에 하나만 사용해도 의미가 충분히 전달될 수 있습니다.
'Language > Java-Weekly-study' 카테고리의 다른 글
[Java] W09: 자바 예외 처리 (0) | 2022.07.13 |
---|---|
[Java] W08: 자바 인터페이스 (0) | 2022.07.12 |
[Java] W06: 자바 상속 (0) | 2022.06.26 |
[Java] W05: 자바 클래스 (0) | 2022.06.19 |
[Java] W04: 자바 제어문 (0) | 2022.06.11 |