본문 바로가기
개발/TIL

[명품 자바 프로그래밍] 6장 - 모듈과 패키지 개념, 자바 기본 패키지

by candosh 2023. 6. 3.

패키지 개념과 필요성

 

디렉터리로 각 개발자의 코드 관리(패키지)

 

자바의 모듈(module)과 패키지(package)

패키지

  • 서로 관련된 클래스와 인터페이스의 컴파일 된 클래스 파일들을 하나의 디렉터리에 묶어 놓은 것

모듈

  • 여러 패키지와 이미지 등의 자원을 모아 놓은 컨테이너
  • JDK 9부터 자바 API의 모든 클래스들(자바 실행 환경)을 패키지 기반에서 모듈들로 완전히 재구성
  • 응용프로그램 역시 여러 개의 모듈로 분할하여 작성 가능
  • 목적
    • 자바 API를 여러 모듈(99개)로 분할하여 응용프로그램의 실행에 적합한 모듈로만 실행 환경을 구축할 수 있도록 함
    • 메모리 등의 자원이 열악한 작은 소형 기기에 꼭 필요한 모듈로 구성된 작은 크기의 실행 이미지를 만들기 위함
  • 모듈의 현실
    • java 9부터 전면적으로 도입, 복잡한 개념, 큰 자바 응용 프로그램에는 개발, 유지보수 등에 적합

패키지명과 클래스의 경로명

  • 점(.)으로 연결
  • ex.
    • Project.FileIO.Tools.class
    • Project.UI.Tools.class

 

패키지 사용하기, import문

다른 패키지에 작성된 클래스
- import를 이용하지 않는 경우

  •  소스 내에서 패키지 이름과 클래스 이름의 전체 경로명을 써주어야 함
public class ImportExample {
	public static void main(String[] args) {
    	java.util.Scanner scanner = new java.util.Scanner(System.in);
    System.out.println(scanner.next());
}

 
- import를 이용하는 경우

  • 소스의 시작 부분에 사용하려는 패키지 명시 (소스에는 클래스 명망 명시하면 됨)
  • 특정 클래스의 경로만 포함 ( ex. import java.util.Scanner;)
import java.util.Scanner;
public class ImportExample {
	public static void main(String[] srgs) {
    	Scanner scanner = new Scanner (System.in);
    }
}
  • 패키지 내의 모든 클래스 포함 ( ex. import.util.*)
  • *는 현재 패키지 내의 클래스 만을 의미하며 하위 패키지의 클래스까지 포함하지 않는다
import java.util.*;
public class ImportExample {
	public static void main(String[] args) {
    	Scanner scanner = new Scanner(System.in);
    }
}

 

패키지 만들기

패키지 선언
- package 패키지명;

  • 컴파일한 클래스 파일을 패키지명의 디렉터리에 저장하라는 지시
  • 소스 파일의 첫 줄에 선언
package UI; //Tools 클래스를 컴파일하려 UI 패키지에 저장할 것을 지시

public class Tools { //이제 이 클래스의 경로명은 UI.Tools가 된다.
......
}
  • Tools 클래스의 경로명은 UI.Tools
  • 다른 클래스에서 Tools 클래스를 사용하기 위해서는 import UI.Tools
package Graphic; //다른 클래스를 Graphic 패키지에 저장

import UI.Tools; // Tools 클래스의 경로명 알림

public class Line {
	public void draw() {
    	Tools t = new Tools();
    }
}

 

디폴트 패키지와 패키지의 특징

- 디폴트 패키지

  • package 선언문이 없이 만들어진 클래스의 패키지
  • 디폴트 패키지는 현재 디렉터리

-패키지의 특징

  • 패키지 계층구조 - 관련된 클래스 파일을 하나의 패키지로 계층화하여 관리 용이
  • 패키지별 접근 제한 - 패키지 별로 접근 
  • 동일한 이름의 클래스와 인터페이스의 사용 가능 - 서로 다른 패키지에 이름이 같은 클래스와 인터페이스 존재 가능
  • 높으 소프트웨어 재사용성

 

모듈 개념

모듈
- Java 9에서 도입된 개념
- 패키지와
- 모듈 파일 ( .jmod )로 저장

자바 모듈화의 목적

가장 큰 목적
- 자바 컴포넌트들을 필요에 따라 조립하여 사용하기 위함
- 컴퓨터 시스템의 불필요한 부담 감소

  • 세밀한 모듈화를 통해 필요 없는 모듈이 로드되지 않게 함
  • 소형 IoT 장치에도 자바 응용 프로그램이 실행되고 성능을 유지하게 함

자바 주요 패키지

- java.lang

  • 자바 language 패키지
  • 스트링, 수학 함수, 입출력 등 자바 프로그램이 필요한 기본적인 클래스와 인터페이스
  • 자동으로 import, import 문이 필요 없음

- java.util

  • 자바 유틸리티 패키지
  • 날짜, 시간, 벡터, 해시맵 등과 같은 다양한 유틸리티 클래스와 인터페이스 제공

- java.io

  • 키보드, 모니터, 프린터, 디스크 등에 입출력을 할 수 있는 클래스와 인터페이스 제공

 

Object 클래스

- 특징

  • java.lang 패키지에 포함
  • 모든 클래스의 슈퍼 클래스
  • 모든 클래스에 강제 상속
  • 모든 객체가 공통으로 가지는 객체의 속성을 나타내는 메소드 보유

- 주요 메소드

  • boolean equals (Object obj) : obj가 가르키는 객체와 현재 객체를 비교하여 같으면 true 리턴
  • Class getClass ( ) : 현 객체의 런타임 클래스를 리턴
  • int hashCode ( ) : 현 객체에 대한 해시 코드 값 리턴
  • String toString ( ) : 현 객체에 대한 문자열 표현 리턴

** equals, hashCode, toString은 오버라이드 해야 함
 

예제 6-1 : Object 클래스로 객체 속성 알아내기
객체 레퍼런스만으로 객체의 클래스명, 해시코드 값, 객체의 문자열을 출력해보자

class Point {
    private int x,y;
    public Point(int x, int y){
        this.x=x;
        this.y=y;
    }
}

public class ObjectPropertyEx {
    public static void print(Object obj){
        System.out.println(obj.getClass().getName());
        System.out.println(obj.hashCode());
        System.out.println(obj.toString());
        System.out.println(obj);
    }
    public static void main(String[] args){
        Point p = new Point(2,3);
        print(p);
    }
}
더보기

Object 클래스는 자바의 모든 클래스의 최상위 클래스이며, 따로 정의하지 않고도 모든 클래스에서 사용할 수 있는 기본 클래스입니다. Object 클래스는 모든 객체에 대한 기본적인 동작을 정의하고 있습니다.

Object 클래스는 많은 유용한 메서드들을 제공합니다. 그 중에서도 가장 일반적으로 사용되는 메서드는 다음과 같습니다:

  1. equals(Object obj): 두 객체가 동등한지를 비교합니다. 기본적으로는 두 객체의 참조값을 비교하지만, 필요에 따라 재정의하여 객체의 내용을 비교할 수도 있습니다.
  2. hashCode(): 객체의 해시 코드를 반환합니다. 해시 코드는 객체를 해시 테이블이나 해시 맵과 같은 자료구조에 사용할 때 유용하게 활용됩니다.
  3. toString(): 객체를 문자열로 표현한 결과를 반환합니다. 기본적으로는 객체의 클래스 이름과 해시 코드를 반환하며, 필요에 따라 재정의하여 객체의 내용을 표현하는 문자열로 변경할 수도 있습니다.
  4. getClass(): 객체의 클래스를 반환합니다.
  5. finalize(): 객체가 가비지 컬렉션되기 전에 호출되는 메서드입니다. 사용되는 경우는 드물며, 일반적으로는 가비지 컬렉션을 통해 자동으로 객체의 메모리가 해제됩니다.

이 외에도 Object 클래스에는 다양한 메서드가 있으며, 필요에 따라 재정의하여 객체의 동작을 커스터마이즈할 수 있습니다.

 

객체를 문자열로 반환 

- String toString( )

  • 객체를 문자열로 반환

 
예제 6-2 : Point 클래스에 toString() 작성
Point 클래스에 Point 객체를 문자열로 리턴하는 toString() 메소드를 작성하라

class Point {
    private int x,y;
    public Point(int x, int y){
        this.x=x;
        this.y=y;
    }
    public String toString() {
        return"Point("+x+","+y+")";
    }
}


public class ToStringEx {
    public static void main(String[] args) {
        Point p = new Point(2, 3);
        System.out.println(p.toString());
        System.out.println(p);  // p.toString() + "입니다"로 자동 변환
        System.out.println(p+"입니다."); // p는 p.toString()으로 자동 변환 System.out.println(p + "입니다.");
    }
}

 

객체 비교와 equals( )

- ==연산자
두 개의 레퍼런스 비교

class Point {
	private int x,y;
    public Point(int x, int y){
    	this.x=x; this.y=y;
    }
}

Point a = new Point(2,3);
Point b = new Point(2,3);
Point c = a;
if(a==b)
	System.out.println("a==b");
if(a==c)
	System.out,println("a==c");

실행 결과

더보기

a==c

- boolean equals(Object obj)
객체 내용이 같은지 비교

class Point {
	private int x,y;
    public Point(int x, int y){
    	this.x=x; this.y=y;
    }
}

Point a = new Point(2,3);
Point b = new Point(2,3);
Point c = new Point(3,4);

if(a==b)
	System.out.println("a==b");
if(a.equals(b))
	System.out.println("a is equals to b");
if(a.equals(c))
	System.out.println("a is equals to c");

실행 결과

더보기

a is equal to b

위: == , 아래: boolean equal

 
예제 6-3 : Point 클래스에 equals() 작성
Point 클래스에 두 점의 좌표가 같으면 true를 리턴하는 equals()를 작성하라.

class Point {
    private int x,y;
    public Point(int x, int y){
        this.x =x; this.y=y;
    }
    public boolean equals(Object obj){
        Point p = (Point)obj;
        if (x==p.x && y==p.y) return true;
        else return false;
    }
}

public class EqualsEx {
    public static void main(String[] args){
        Point a = new Point(2,3);
        Point b = new Point(2,3);
        Point c = new Point(3,4);

        if (a==b) //false
            System.out.println("a==b");
        if (a.equals(b)) //true
            System.out.println("a is equal to b");
        if (a.equals(c)) //false
            System.out.println("a is equal to c");
    }
}

 
예제 6-4 : Rect 클래스와 equals() 만들기 연습
int타입의 width(너비)와 height(높이) 필드를 가지는 Rect 클래스를 작성하고, 면적이 같으면 두 Rect객체가 같은 것으로 판별하는 equals()를 작성하라. 생성자에서 너비와 높이를 받아 width, height 필드를 초기화하라.

class Point {
    private int x,y;
    public Point(int x, int y){
        this.x =x; this.y=y;
    }
    public boolean equals(Object obj){
        Point p = (Point)obj;
        if (x==p.x && y==p.y) return true;
        else return false;
    }
}

public class EqualsEx {
    public static void main(String[] args){
        Point a = new Point(2,3);
        Point b = new Point(2,3);
        Point c = new Point(3,4);

        if (a==b) //false
            System.out.println("a==b");
        if (a.equals(b)) //true
            System.out.println("a is equal to b");
        if (a.equals(c)) //false
            System.out.println("a is equal to c");
    }
}

 

Wrapper 클래스

자바의 기본 타입을 클래스화한 8개 클래스

기본 타입 byte short int long char float double boolean
Wrapper
클래스
Byte Short Integer Long Character Float Double Boolean
  • 이름이 Wrapper인 클래스는 존재하지 않음
  • 용도 : 기본 타입의 값을 객체로 다룰 수 있게 함

 

Wrapper 객체 생성

기본 타입의 값으로 Wrapper 객체 생성

  • integer i = Integer.valueOf(10);
  • Character c = Character.value('c');
  • Double f = Double.valueOf(3.14);
  • Boolean b = Boolean.valueOf(true);

문자열로 Wrapper 객체 생성

  • Inter I = Integer.valueOf("10");
  • Double d = Double.valueOf("3.14");
  • Boolean b = Boolean.valueOf("false");

Float 객체는 double 타입의 값으로 생성 가능

  • Float f = Float.valueOf((double)3.14);

 
주요 메소드

  • Wrapper 객체들은 거의 유사, 많은 메소드가 static 타입

Integer 클래스의 주요 메소드

메소드 설명
static int bitCount(int i) 정수 i의 이진수 표현에서 1의 개수 리턴
float floatValue() float 타입으로 값 리턴
int intValue() int 타입으로 값 리턴
long longValue() long 타입으로 값 리턴
short shortValue() short 타입으로 값 리턴
static int parseInt(String s) 문자열 s를 10진 정수로 변환한 값 리턴
static int parseInt(String s, int radix) 문자열 s를 지정된 진법의 정수로 변환한 값 리턴
static String toBinaryString(int i) 정수 i를 이진수 표현으로 변환한 문자열 리턴
static String toHexString(int i) 정수 i를 16진수 표현으로 변환한 문자열 리턴
static String toOctalString 정수 i를 8진수 표현으로 변환한 문자열 리턴
static String toString(int i) 정수 i를 문자열로 변환하여 리턴
static Integer valueOf(int i) 정수 i를 담은 Integer 객체 리턴
static Integer valueOf(String s) 문자열 s를 정수로 변환하여 담고 있는 Integer 객체 리턴

 
예제 6-5 : wrapper 클래스 활용

public class WrapperEx {
    public static void main(String[] args){
        System.out.println(Character.toLowerCase('A')); //'A'를 소문자로 변환
        char c1='4', c2='F';
        if(Character.isDigit(c1)) //문자 c1이 숫자면 true
            System.out.println(c1+"는 숫자");
        if (Character.isAlphabetic(c2)) //문자 c2가 영문자면 true
            System.out.println(c2+"는 영문자");

        System.out.println(Integer.parseInt("-123")); //"-123"을 10진수로 변환
        System.out.println(Integer.toHexString(28)); //정수 28을 2진수 문자열로 변환
        System.out.println(Integer.toBinaryString(28)); //28을 16진수 문자열로 변환
        System.out.println(Integer.bitCount(28)); //28에 대한 2진수의 1의 개수

        Double d = Double.valueOf(3.14);
        System.out.println(d.toString()); //Double을 문자열 "3.14"로 변환
        System.out.println(Double.parseDouble("3.14")); //문자열을 실수 3.14로 변환

        boolean b = (4>3); //b는 true
        System.out.println(Boolean.toString(b)); //true를 문자열 "true"로 변환
        System.out.println(Boolean.parseBoolean("false")); //문자열을 false로 변환
    }
}

실행 결과

더보기

a
4는 숫자
F는 영문자
-123
1c
11100
3
3.14
3.14
true
false

 

박싱과 언박싱

박싱 (boxing)

  • 기본 타입의 값을 Wrapper 객체로 변환

언박싱(unboxing)

  • Wrapper 객체에 들어 있는 기본 타입의 값을 빼내는 것

자동 박싱과 자동 언박싱 - JDK1.5부터

Integer ten = 10; //자동 박싱. Integer ten = Integer.valueOf(10);로 자동 처리
int n = ten; //자동 언박싱. int n = ten.intValue();로 자동 처리

 
예제 6-6 : 박싱 언박싱

public class AutoUnBoxingEx{
	public static void main(String[] srgs){
    int n = 10;
    Integer intObject = n; //auto boxing
    System.out.println("inObject = " + intObject);
    
    int m = intObject + 10; //auto unboxing
    System.out.println("m = "+ m);
    }
}

실행 결과

더보기

intObject = 10

m = 20

 

String의 특징과 객체 생성

String - java.lang.String

  • String 클래스는 하나의 문자열로 표현
//스트링 리터럴로 스트링 객체 생성
String str1 = "abcd";

//String 클래스의 생성자를 이용하여 스트링 생성
char data[] = {'a','b','c','d'};
String str2 = new String(data);
String str3 = new String("abcd"); //str2와 str3은 모두 "abcd" 스트링

String 생성자

생성자 설명
String() 빈 스트링 객체 생성
String(char[] value) char 배열에 있는 문자들을 스트링 객체로 생성
String(String original) 매개변수로 주어진 문자열과 동일한 스트링 객체 생성
String(StringBuffer buffer) 매개변수로 주어진 스트링 버퍼의 문자열을 스트링 객체로 생성

 

스트링 리터럴과 new String()

스트링 생성 방법

  • 리터럴로 생성, String s = "Hello";
    • JVM이 리터럴 관리, 응용프로그램 내에서 공유됨
  • String 객체로 생성, String t = new String("Hello");
    • 힙 메모리에 String 객체 생성

자바 가상 기꼐의 스트링 리터럴 테이블

 

스트링 객체의 주요 특징

스트링 객체는 수정 불가능 (immutable)

String s = new String("Hello");
String t = s.concat("Java"); //스트링 s에 "Java"를 덧붙인 새로운 스트링 객체 리턴

스트링 비교 시 반드시 equals()를 사용

  • equals()는 내용을 비교하기 때문

 
주요 메소드

** String concat(String str), boolean contains(CharSequence s), String trim()
 

문자열 비교

int compareTo(String anotherString)

  • 문자열이 같으면 0리턴
  • 이 문자열이 anotherString 보다 사전에 먼저 나오면 음수 리턴
  • 이 문자열이 anotherString보다 사전에서 나중에 나오면 양수 리턴
String java = "Java";
String cpp = "C++";
int res = java.compareTo(cpp);
if(res==0)
	System.out.println("the same");
else if(res<0)
	System.out.println(java + "<" + cpp);
else
	System.out.println(java + ">" + cpp);

실행 결과

더보기

Java > C++  //"Java"가 "C++"보다 사전에서 나중에 나오기 때문에 양수 리턴

 

문자열 연결

+연산자로 문자열 연결

  • 피연산자에 문자열이나 객체가 포함되어 있는 경우
  • 객체는 객체.toString()을 호출하여 문자열로 변환하여 연결
  • 기본 타입 값은 문자열로 변환하여 연결

String concat(String str)를 이용한 문자열 연결

  • ex. "I love ".concat("Java")는 "I love Java"리턴
  • 기존 String 객체에 연결되지 않고 새로운 스트링 객체 리턴
  • concat은 새로운 문자열을 생성

문자열 내의 공백 제거, 문자열의 각 문자 접근
공백 제거

  • String trim()
  • 문자열 앞 위 공백 문자(tab, enter, space) 제거한 문자열 리턴
String a = " abcd def ";
String b = " xyz\t";
String c = a.trim(); // c = "abcd def". 문자열 중간에 있는 공백은 제거되지 않음 
String d = b.trim(); // d = "xyz". 스페이스와 '\t' 제거됨"

 
문자열의 문자

  • char charAt(int index)
  • 문자열 내의 문자 접근
// "class"에 포함된 ‘s’의 개수를 세는 코드
int count = 0;
String a = "class";
for(int i=0; i<a.length(); i++) { // a.length()는 5
if(a.charAt(i) == 's') count++;
}
System.out.println(count); // 2 출력

 
예제 6-7 : String 클래스 메소드 활용

예제 실행 과정

StringBuffer 클래스

  • 가변 크기의 문자열 저장 클래스
    • Java.lang.StringBuffer
    • String 클래스와 달리 문자열 변경 가능
    • String 객체의 크기는 스트링 길이에 따라 가변적
    • 동기화 되어 있음
  • 생성
    • StringBuffer sb = new StringBuffer("java");
생성자 설명
StringBuffer() 초기 버퍼 크기가 16인 스트링 버퍼 객체 생성
StringBuffer(charSequence seq) seq가 지정하는 일련의 문자들을 포함하는 스트링 버퍼 생성
StringBuffer(int capacitiy) 지정된 초기 크기를 갖는 스트링 버퍼 객체 생성
StringBuffer(String str) 지정된 스트링으로 초기화된 스트링 버퍼 객체 생성

 
주요 메소드

StringBuffer의 메소드 활용 예

**capacity와 length의 차이
 

예제 6-8 : StringBuffer 클래스 메소드 활용

public class StringBufferEx {
	public static void main(String[] args) {
		StringBuffer sb = new StringBuffer("This"); 
        
		sb.append(" is pencil"); // 문자열 덧붙이기
		System.out.println(sb);
        
        	sb.insert(7, " my"); // "my" 문자열 삽입 
		System.out.println(sb);

		sb.replace(8, 10, "your"); // "my"를 "your"로 변경 
		System.out.println(sb);

		sb.delete(8, 13); // "your " 삭제 
		System.out.println(sb);

		sb.setLength(4); // 스트링 버퍼 내 문자열 길이 수정 
		System.out.println(sb);
	} 
}

실행 결과

더보기

This is pencil
This is my pencil

This is your pencil

This is pencil
This

 

StringTokenizer 클래스

java.util.StringTokenizer

  • 하나의 문자열을 여러 문자열 분리
  • 문자욜을 분리할 때 사용되는 기준 문자 : 구분 문자(delimiter)
  • 토큰(token) - 구분 문자로 분리된 문자열
  • String 클래스의 split() 메소드를 이용하여 동일한 구현 가능

StringTokenizer 객체 생성과 문자열 분리

 
생성자와 주요 메소드
생성자

생성자 설명
StringTokenizer(String str) str 스트링의 각 문자를 구분 문자로 문자열을 분리하는 스트링 토크나이저 생성
StringTokenizer(String str, String delim) str 스트링과 delim 구분 문자로 문자열을 분리하는 스트링 토크나이저 생성
StringTokenizer(String str, String delim, boolean returnDelims) str 스트링과 delim 구분 문자로 문자열을 분리하는 스트링 토크나이저 생성, returnDelims가 true이면 delim이 포함된 문자도 토큰에 포함된다.

주요 메소드

메소드 설명
int countTokens() 스트링 토크나이저가 분리한 토큰 개수 리턴
boolean hasMoreTokens() 스트링 토크나이저에 다음 토큰이 있으면 true리턴
String nextToken() 스트링 토크나이저에 들어 있는 다음 토큰 리턴

 
예제 6-9 : StringTokenizer 클래스 메소드 활용

import java.util.StringTokenizer;

public class StringTokenizerEx{
	pubilc staric void main(String[] srgs) {
    	StringTokenizer st = new StringTokenizer("홍길동/장화/홍련/콩쥐/팥쥐", "/");
        while(st.hasMoreTokens())
        	System.out.println(st.nextToken());
    }
}

 

Math 클래스

  • 산술 연산 메소드 제공, java.lang.Math
  • 모든 메소드는 static 타입 : 클래스 이름으로 바로 호출해야 함

 

Calendar 클래스

  • java.util 패키지
  • 시간과 날짜 정보 저장 관리

명품 자바 프로그래밍 - 개정판 4판/ 황기태