[Java] 명품 Java Programming 정리 - 6장

근이의 개발일기·2024년 8월 19일
0
post-thumbnail

6장

패키지와 모듈

  • 패키지:
    • 서로 관련된 클래스와 인터페이스의 컴파일된 클래스 파일들을 하나의 디렉터리에 묶어 놓은 것
  • 모듈
    • 여러 패키지와 이미지 등의 자원을 모아 놓은 컨테이너
      • 모듈 파일에는 자바 API의 패키지와 클래스들이 들어있음
    • 자바가 설치된 jmods 디렉터리에 모듈파일 존재
      • 모듈파일(.jmod 파일)은 ZIP 포맷으로 압축된 파일
      • 자바 버전에 따라 100개에 가까운 모듈파일 제공
    • Jmod 명령을 이용하여 모듈 파일에 들어있는 패키지를 풀어 낼 수 있음
    • JDK9부터 자바 API의 모든 클래스(JRE; 자바 실행환경)들을 패키지 기반에서 모듈들로 완전히 재구성
    • 응용 프로그램 역시 여러 개의 모듈로 분할하여 작성 가능
      • 클래스들은 패키지로 만들고, 다시 패키지를 모듈로 만듬
  • 모듈의 목적
    • 자바 API를 여러 모듈로 분할하여 응용프로그램의 실행에 적합한 모듈들로만 실행환경을 구축할 수 있도록 함
    • 메모리 등의 자원이 열악한 작은 소형 기기에 꼭 필요한 모듈로 구성된 작은 크기의 실행 이미지를 만들기 위함
    • Java9부터 전면적으로 도입, 복잡한 개념, 큰 자바 응용프로그램에는 개발, 유지보수 등에 적합

중요 Object 클래스

  • Object 클래스
    • java.lang 패키지에 포함
    • 모든 클래스의 수퍼 클래스임
      • 모든 클래스에 강제 상속
      • 모든 객체가 공통으로 가지는 객체의 속성을 나타내는 메소드 보유
    • 주요 메소드: Untitled
      • equals(), hashCode(), toString은 클래스 디자인 시 오버라이딩 필수이다

      • 오버라이딩 해주지 않으면 Object클래스에 기본으로 설정된 대로 값을 리턴한다.

        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);
            }
        }

        출력결과:

        Point

        366712642

        Point@15db9742

        Point@15db9742

        주의! hashCode() 함수는 int형으로 해시코드를 리턴하지만, default toString함수에서는 16진수형태로 해시코드를 리턴한다.

        주의! .getClass()를 통해서 런타임 객체를 리턴한 후에 getName()을 통해 클래스의 이름을 리턴한다. (실행중인 객체의 이름을 리턴함) 객체에 바로 getName() 사용할 수 없다!

객체 문자열 변환; toString()

  • String toString()
    • 객체를 문자열로 반환
    • Object 클래스에 구현된 toString()이 반환하는 문자열 Untitled
      • 클래스 타입 이름에 16진수 해쉬코드를 합쳐서 문자열 형태로 반환해줌
    • ‘객체 + 문자열’ → ‘객체.toString() + 문자열’로 자동변환 Untitled
      • 주의! toString 자동 변환 조건 Java에서 toString() 메소드가 발현되는 조건은 다음과 같습니다:
        1. 객체를 출력할 때: System.out.println() 또는 System.out.print()와 같은 출력 메소드를 사용하여 객체를 출력할 때 toString() 메소드가 호출됩니다.

          java코드 복사
          MyClass obj = new MyClass();
          System.out.println(obj); // toString() 호출됨
        2. 문자열 연결: 문자열과 객체를 + 연산자로 연결할 때 객체의 toString() 메소드가 자동으로 호출됩니다.

          java코드 복사
          MyClass obj = new MyClass();
          String str = "Object: " + obj; // toString() 호출됨
        3. 문자열 형식화: String.format() 메소드를 사용하여 문자열을 형식화할 때 객체가 문자열로 변환될 때 toString() 메소드가 호출됩니다.

          java코드 복사
          MyClass obj = new MyClass();
          String str = String.format("Object: %s", obj); // toString() 호출됨
        4. 문자열을 필요로 하는 다른 메소드: 객체를 문자열로 표현하는 다른 메소드에서 필요할 때 toString() 메소드가 호출됩니다.

          ```java
          java코드 복사
          MyClass obj = new MyClass();
          someMethod(obj); // 메소드 내부에서 obj.toString() 호출됨
          ```

          일반적으로 toString() 메소드를 오버라이딩하여 객체의 문자열 표현을 사용자가 읽기 쉽게 만듭니다. 객체에 대한 유용한 정보를 문자열로 반환하도록 구현할 수 있습니다. 이를 통해 디버깅 및 로깅을 쉽게 할 수 있습니다.

    • 개발자는 자신만의 toString() 작성 필요
      • Object의 toString() 오버라이딩과 같음

      • 주의! public으로 지정하여서 오버라이딩 해주어야함

        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 ObjectPropertyEx {
            public static void main(String[] args) {
                Point p = new Point(2,3);
                System.out.println(p.toString());
                System.out.println(p);
                System.out.println(p+"입니다.");
            }
        }
        

        출력 결과:

        Point(2,3)
        Point(2,3)
        Point(2,3)입니다.

        주의! 문자열이 쓰이는 곳에서 객체 이름을 써준다면 자동으로 toString을 호출한다. ← 그렇기 때문에 public으로 처리해주어야함

객체 비교; equals()

  • == 연산자: 두개의 레퍼런스 값 비교
  • boolean equals(Object obj): 객체 내용이 같은지 비교 주의! 리턴형 boolean 형인 것 주의하기 bool 아님! Untitled Untitled 주의! 오버라이딩 시에 매개변수까지 같아야 오버라이딩 되기떄문에 매개변수는 Object로 받아줘야한다. 그 후에 Object형에서 해당 객체로 강제 형변환을 통해서 바꿔줘야함 Point 클래스에 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 ObjectPropertyEx {
        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)
                System.out.println("a==b");
            if(a.equals(b))
                System.out.println("a is equal to b");
            if(a.equals(c))
                System.out.println("a is equal to c");
        }
    }
    
    출력 결과: a is equal to b Rect 클래스와 equals() 작성 예시
    class Rect {
        private int width;
        private int height;
        public Rect(int width, int height){
            this.width = width;
            this.height = height;
        }
        public boolean equals(Object obj){
            Rect p = (Rect)obj;
            if (width*height == p.width*p.height)
                return true;
            else
                return false;
        }
    }
    public class EqualsEx {
        public static void main(String[] args) {
            Rect a = new Rect(2,3);
            Rect b = new Rect(3,2);
            Rect c = new Rect(3,4);
            if(a.equals(b))
                System.out.println("a is equal to b");
            if(a.equals(c))
                System.out.println("a is equal to c");
            if(b.equals(c))
                System.out.println("b is equal to c");
        }
    }
    
    출력 결과: a is equal to b

중요 Wrapper 클래스

  • Wrapper 클래스: 자바의 기본 타입을 클래스화 한 8개의 클래스이다. Untitled
    • int형은 Integer, char형은 Character이고, 나머지 자료형은 전부 앞의 알파벳만 소문자로 바꾸어주면 된다.
    • 이름이 Wrapper인 클래스는 존재하지 않음
    • 기본 타입의 값을 객체로 다룰 수 있게 함
  • Wrapper 객체 생성
    • 기본 타입의 값으로 Wrapper 객체 생성 Untitled
    • 문자열로 Wrapper 객체 생성 Untitled
    • Float객체는 double 타입의 값으로도 생성가능 Untitled
    • 주의! Java 9부터 생성자를 이용한 Wrapper 객체 생성 폐기
  • 주요 메소드
    • Wrapper 객체들은 거의 유사함, 많은 메소드가 static 타입으로 이루어짐
    • 중요 Integer 클래스의 주요 메소드 Untitled
  • 중요 Wrapper 클래스의 활용
    • Wrapper 객체로부터 기본 타입 값 알아내기 Untitled
    • 문자열을 기본 데이터 타입으로 변환 Untitled
    • 기본 타입을 문자열로 변환 Untitled Ex) 중요 int, Integer, String 사이의 변환 int -[ Integer.valueOf(int_value) ]→ Integer int -[Integer.toString(int_value) ]→ String Integer -[ (Integer_reference).intValue() ]→ int Integer -[ (Integer_reference).toString() ]→ String String -[ Integer.valueOf(num_String) ]→ Integer String -[ Integer.parseInt(num_String) ]→ int

Wrapper 클래스 활용

public class WrapperEx {
    public static void main(String[] args) {
        System.out.println(Character.toLowerCase('A')); //대문자 -> 소문자 출력, 소문자 -> 소문자 출력
        char c1='4', c2='a';
        if(Character.isDigit(c1))
            System.out.println(c1);
        if(Character.isAlphabetic((c2)))
            System.out.println(c2+"는 영문자");

        System.out.println(Integer.parseInt("-123"));
        System.out.println(Integer.toHexString(28));
        System.out.println(Integer.toBinaryString(28));
        System.out.println(Integer.bitCount(28));

        Double d = Double.valueOf(3.14);
        System.out.println(d.toString());
        System.out.println(Double.parseDouble("3.14"));

        boolean b = (4>3);
        System.out.println(Boolean.toString(b));
        System.out.println(Boolean.parseBoolean("true"));
    }
}

출력 결과:

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

중요

Charater 클래스 메소드

  • toLowerCase(): 대문자 알파벳을 소문자로 바꿔줌, 대문자 알파벳이 아닌 경우 그대로 출력함
  • isDigit(): 숫자인 char인지 검사 (유니코드상 숫자형식인지 검사)
    • isDigit() 추가설명 Character.isAlphabetic(int codePoint) 메서드는 자바에서 주어진 코드 포인트가 알파벳 문자인지 여부를 확인하는 데 사용됩니다. 이 메서드는 유니코드 표준에 따라 문자가 알파벳 문자인지 확인합니다.

      메서드 정의

      java코드 복사
      public static boolean isAlphabetic(int codePoint)
      

      파라미터

      • codePoint: 확인할 유니코드 코드 포인트입니다. 이 값은 char 타입의 문자 또는 int 타입의 유니코드 코드 포인트일 수 있습니다.

        반환값

      • true: 주어진 코드 포인트가 알파벳 문자일 경우.

      • false: 주어진 코드 포인트가 알파벳 문자가 아닐 경우.

        작동 방식

        이 메서드는 유니코드 범주를 기준으로 문자를 알파벳으로 간주합니다. 유니코드에서 알파벳 문자로 분류되는 문자는 다음과 같은 범주에 속합니다:

      • UPPERCASE_LETTER (대문자)

      • LOWERCASE_LETTER (소문자)

      • TITLECASE_LETTER (타이틀 케이스 문자)

      • MODIFIER_LETTER (수정자 문자)

      • OTHER_LETTER (기타 문자)

      • LETTER_NUMBER (문자 숫자)

        예제 코드

        java코드 복사
        public class AlphabeticCheck {
            public static void main(String[] args) {
                char c1 = 'A';
                char c2 = '1';
                char c3 = 'α'; // Greek letter alpha
        
                // Check if c1 is alphabetic
                if (Character.isAlphabetic(c1)) {
                    System.out.println(c1 + " is an alphabetic character.");
                } else {
                    System.out.println(c1 + " is not an alphabetic character.");
                }
        
                // Check if c2 is alphabetic
                if (Character.isAlphabetic(c2)) {
                    System.out.println(c2 + " is an alphabetic character.");
                } else {
                    System.out.println(c2 + " is not an alphabetic character.");
                }
        
                // Check if c3 is alphabetic
                if (Character.isAlphabetic(c3)) {
                    System.out.println(c3 + " is an alphabetic character.");
                } else {
                    System.out.println(c3 + " is not an alphabetic character.");
                }
            }
        }
        

        예제 설명

      1. char c1 = 'A';:

        • 'A'는 대문자 알파벳이므로 Character.isAlphabetic(c1)true를 반환합니다.
      2. char c2 = '1';:

        • '1'은 숫자 문자이므로 Character.isAlphabetic(c2)false를 반환합니다.
      3. char c3 = 'α';:
        - 'α'는 그리스 문자 알파로, 유니코드에서 알파벳 문자로 분류되므로 Character.isAlphabetic(c3)true를 반환합니다.

        주의사항

      • Character.isAlphabetic(int codePoint)char뿐만 아니라 유니코드 코드 포인트를 받을 수 있습니다. 유니코드 코드 포인트는 정수형 int로 표현할 수 있습니다.

      • 16비트 char 타입의 문자로는 표현할 수 없는 보충 문자(supplementary characters)를 다룰 때 유용합니다.

        결론

        Character.isAlphabetic(int codePoint) 메서드는 주어진 유니코드 코드 포인트가 알파벳 문자인지 여부를 판단하는 데 사용됩니다. 이는 다양한 언어의 문자 및 유니코드 문자를 포함하는 모든 알파벳 문자를 처리할 수 있어, 전 세계의 다양한 언어 지원이 가능합니다.

  • isAlphabetic(): 영문자 char인지 검사 (유니코드상 문자; 한글포함)
    • isAlphabetic() 추가 설명 Character.isDigit(int codePoint) 메서드는 주어진 코드 포인트가 10진 숫자(digit)인지 여부를 확인하는 데 사용됩니다. 이 메서드는 유니코드 표준에 따라 문자가 0부터 9까지의 숫자(디지털 문자)인지 확인합니다.

      메서드 정의

      java코드 복사
      public static boolean isDigit(int codePoint)
      

      파라미터

      • codePoint: 확인할 유니코드 코드 포인트입니다. 이 값은 char 타입의 문자 또는 int 타입의 유니코드 코드 포인트일 수 있습니다.

        반환값

      • true: 주어진 코드 포인트가 10진 숫자일 경우.

      • false: 주어진 코드 포인트가 10진 숫자가 아닐 경우.

        작동 방식

        이 메서드는 유니코드 표준을 기반으로 코드 포인트가 숫자 문자인지를 확인합니다. 유니코드에서 숫자 문자로 분류되는 문자는 다음과 같은 범주에 속합니다:

      • DECIMAL_DIGIT_NUMBER (유니코드 카테고리)

        예제 코드

        java코드 복사
        public class DigitCheck {
            public static void main(String[] args) {
                char c1 = '5';
                char c2 = 'A';
                char c3 = '٢'; // Arabic-Indic digit two
        
                // Check if c1 is a digit
                if (Character.isDigit(c1)) {
                    System.out.println(c1 + " is a digit.");
                } else {
                    System.out.println(c1 + " is not a digit.");
                }
        
                // Check if c2 is a digit
                if (Character.isDigit(c2)) {
                    System.out.println(c2 + " is a digit.");
                } else {
                    System.out.println(c2 + " is not a digit.");
                }
        
                // Check if c3 is a digit
                if (Character.isDigit(c3)) {
                    System.out.println(c3 + " is a digit.");
                } else {
                    System.out.println(c3 + " is not a digit.");
                }
            }
        }
        

        예제 설명

      1. char c1 = '5';:

        • '5'는 10진수 숫자이므로 Character.isDigit(c1)true를 반환합니다.
      2. char c2 = 'A';:

        • 'A'는 알파벳 문자이므로 Character.isDigit(c2)false를 반환합니다.
      3. char c3 = '٢';:
        - '٢'는 아라비아-인디언 숫자 2로, 유니코드 표준에서 숫자로 분류되므로 Character.isDigit(c3)true를 반환합니다.

        추가 설명

      • Character.isDigit(int codePoint)는 0부터 9까지의 아라비아 숫자뿐만 아니라, 유니코드에서 숫자로 분류된 모든 문자를 판별합니다.

      • 유니코드에는 다양한 숫자 형식이 포함되어 있습니다. 예를 들어:
        - 아라비아 숫자: '0'부터 '9' (U+0030 to U+0039)
        - 아라비아-인디언 숫자: '٠'부터 '٩' (U+0660 to U+0669)
        - 데바나가리 숫자: '०'부터 '९' (U+0966 to U+096F)

        결론

        Character.isDigit(int codePoint) 메서드는 주어진 유니코드 코드 포인트가 10진수 숫자인지 여부를 확인합니다. 이 메서드는 0부터 9까지의 아라비아 숫자뿐만 아니라, 유니코드에서 숫자로 분류된 다양한 숫자 형식을 포함하여 판별합니다. 따라서, 이는 다국어 환경에서 숫자 문자를 정확히 식별하는 데 유용합니다.

Integer 클래스 메소드

  • bitCount(): 이진수의 bit중 1의 개수를 세서 리턴한다 (Long 클래스에서도 사용가능)

Boolean 클래스 메소드

  • parseBoolean(): true이외의 문자열을 전부 false를 리턴한다. true의 경우는 대소문자에 관계없이 true를 리턴한다. (TrUe → true 리턴)

중요 Wrapper 클래스 박싱과 언박싱

  • 박싱: 기본타입의 값을 Wrapper 객체로 변환
  • 언박싱: Wrapper 객체에 들어있는 기본 타입의 값을 빼내는 것

Untitled

  • 자동 박싱과 자동 언박싱 - Java 5부터 Untitled
    • 객체로써 사용해야할때(함수나 클래스에서 사용) 자동 박싱, 언박싱을 통해 간편히 사용가능

      ex) void push(Object o) → i.push(10); 
      
            Object pop() → int k = p.pop();

      박싱 언박싱 예제

      public class AutoBoxingUnBoxingEx {
          public static void main(String[] args) {
              int n = 10;
              Integer intObject = n;
              System.out.println("intObject = "+intObject);
      
              int m = intObject + 10;
              System.out.println("m ="+m);
          }
      }

      출력 결과:

      intObject = 10
      m =20

      주의! int형 타입과 Interger형 객체를 연산하면 Integer 객체가 unbox되면서 계산이 이루어진다

      박싱 언박싱의 활용 예제1 (Object 클래스 사용)

      public class test {
          public static void main(String[] args) {
              Object obj1 = getObject("Hello, World!");
              Object obj2 = getObject(12345);
              Object obj3 = getObject(12.34);
      
              System.out.println(obj1);
              System.out.println(obj2);
              System.out.println(obj3);
          }
      
          public static Object getObject(Object input) {
              return input;
          }
      }

      출력 결과:

      Hello, World!
      12345
      12.34

      중요 위의 형식으로 Object 클래스를 활용한 입출력에 기본 값을 boxing, unboxing해줄 수 있다.

      Ex) Object input = 12345 → 12345가 Integer.valueOf(12345)로 자동 박싱

      박싱 언박싱의 활용 예제2 (Object 클래스 사용)

      public class ObjectReturnExample {
          public static void main(String[] args) {
              Object obj = getObject("Hello, World!");
      
              // obj를 String 타입으로 캐스팅
              if (obj instanceof String) {
                  String str = (String) obj;
                  System.out.println("String value: " + str);
              }
      
              obj = getObject(12345);
      
              // obj를 Integer 타입으로 캐스팅
              if (obj instanceof Integer) {
                  int num = (Integer) obj;
                  System.out.println("Integer value: " + num);
              }
          }
      
          public static Object getObject(Object input) {
              return input;
          }
      }

      출력 결과:

      String value: Hello, World!

      Integer value: 12345

      주의! Object로 반환된 객체를 사용할 때는 원래 타입으로 캐스팅 해야하는데, 이 때, 캐스팅은 런타임 에러이다. 그러므로, 잘못된 타입으로 캐스팅하면 ‘ClassCastException’의 예외가 발생한다.

      박싱 언박싱의 활용 예제3 (캐스팅 런타임 오류)

      public class test {
          public static void main(String[] args) {
              Object obj1 = getObject("Hello, World!");
              Object obj2 = getObject(12345);
              Object obj3 = getObject(12.34f);
      
              System.out.println("obj1: "+obj1);
      
              //int i1=2+(byte)obj2;
              //int i2=2+(short)obj2;
              int i3=2+(int)obj2;
              //int i4=2+(long)obj2;
              //int i5=2+(Byte)obj2;
              //int i6=2+(Short) obj2;
              int i7=2+(Integer)obj2;
              //int i8=2+(Long)obj2;
      
              //System.out.println("i: "+i1);
              //System.out.println("i: "+i2);
              System.out.println("i: "+i3);
              //System.out.println("i: "+i4);
              //System.out.println("i: "+i5);
              //System.out.println("i: "+i6);
              System.out.println("i: "+i7);
              //System.out.println("i: "+i8);
      
              double d1=2+(float)obj3;
              //double d2=2+(double)obj3;
              double d3=2+(Float)obj3;
              //double d4=2+(Double)obj3;
              System.out.println("d: "+d1);
              //System.out.println("d: "+d2);
              System.out.println("d: "+d3);
              //System.out.println("d: "+d4);
          }
      
          public static Object getObject(Object input) {
              return input;
          }
      }

      출력 결과:

      obj1: Hello, World!
      i: 12347
      i: 12347
      d: 14.34000015258789
      d: 14.34000015258789

      주의! 캐스팅은 기본 자료형으로 하든 Wrapper 클래스로 하든 상관없이 캐스팅된다. 그러나, 딱 맞는 자료형이 아니면 무조건 오류가 난다. 참고로 12.32 같은 실수형 literal은 기본적으로 double 형이고, 12.32f로 명시해주어야 float형으로 인식한다.

String의 특징과 객체 생성

  • String - java.lang.String
    • String 클래스는 하나의 문자열을 표현한다 Untitled
    • 중요 String 객체 생성 및 초기화 방법
      • String 리터럴을 사용한 초기화
      • new String(클래스의 생성자)를 이용한 초기화
        1. char형 배열을 대입
        2. String 리터럴 대입
        3. String 객체 대입
        4. 바이트 배열 대입 (바이트 값→ 아스키코드 값)
        5. StringBuffer 대입
        • 주의! char형 배열을 직접적으로 String에 대입 불가
      • StringBuilder, StringBuffer의 toString() 메소드를 이용한 초기화
      • String.format() 메소드를 통해 printf()의 형식으로 초기화
      • String.valueOf를 통한 초기화
    • String 생성자 종류 Untitled
  • 스트링 리터럴과 new String()
    • 리터럴로 생성

      • JVM이 리터럴 관리; String Pool이라는 공간에서 따로 관리함, 응용 프로그램 내에서 공유됨
    • String 객체로 생성
      - 힙 메모리에 String 객체 생성

      Untitled

      주의! intern() 함수를 통해 String 리터럴의 참조를 리턴하여 공유할 수 있게 한다.

    • intern() 함수 사용법

      intern() 메서드는 자바의 String 클래스에서 제공하는 메서드로, 문자열의 인턴(pooling)을 관리하는 데 사용됩니다. 이 메서드는 특정 문자열을 풀(pool)에 넣고, 동일한 문자열이 이미 존재하는 경우 그 문자열의 참조를 반환합니다. 이를 통해 문자열 리터럴이 동일한 인스턴스를 공유하게 되어 메모리 사용을 최적화할 수 있습니다.

      주요 개념

      • String Constant Pool: 자바는 문자열 리터럴을 위한 특별한 메모리 영역을 가지고 있습니다. 이 영역을 문자열 상수 풀(string constant pool)이라고 부릅니다. 동일한 문자열 리터럴은 이 풀에서 단 하나의 인스턴스를 공유합니다.

      • Interning: 문자열을 이 풀에 저장하고, 동일한 내용의 문자열이 이미 존재하는 경우 그 참조를 반환하는 과정입니다.

        intern() 메서드의 작동 방식

      • intern() 메서드는 호출된 문자열의 참조를 문자열 상수 풀에 저장합니다.

      • 동일한 문자열이 이미 상수 풀에 존재하면 그 문자열의 참조를 반환합니다.

      • 상수 풀에 존재하지 않으면, 현재 문자열을 상수 풀에 추가하고 그 참조를 반환합니다.

        예제 코드

        java코드 복사
        public class StringInternExample {
            public static void main(String[] args) {
                // 문자열 리터럴은 자동으로 상수 풀에 저장됩니다.
                String str1 = "Hello";
                String str2 = "Hello";
        
                // str1과 str2는 동일한 참조를 가리킵니다.
                System.out.println(str1 == str2); // 출력: true
        
                // new 연산자를 사용하면 새로운 인스턴스가 생성됩니다.
                String str3 = new String("Hello");
        
                // str1과 str3는 동일한 내용을 가지고 있지만, 다른 참조를 가리킵니다.
                System.out.println(str1 == str3); // 출력: false
        
                // intern() 메서드를 호출하여 str3(의 String값)를 상수 풀에 추가합니다.
                String str4 = str3.intern();
        
                // str1과 str4는 동일한 참조를 가리킵니다.
                System.out.println(str1 == str4); // 출력: true
                // 주의! str1과 str3는 다른 참조를 가리킵니다. str3는 여전히 heap의 메모리 공간을 참조하기 떄문입니다.
                System.out.println(str1 == str3); // 출력: false
            }
        }
        

        설명

      1. 문자열 리터럴:

        • String str1 = "Hello";String str2 = "Hello";는 동일한 참조를 가리킵니다. 이는 문자열 리터럴이 상수 풀에 저장되기 때문입니다.
      2. new 연산자:

        • String str3 = new String("Hello");는 새로운 String 객체를 생성합니다. 따라서 str1str3는 동일한 내용을 가지지만, 다른 참조를 가리킵니다.
      3. intern() 메서드:
        - String str4 = str3.intern();str3의 문자열을 상수 풀에 추가하거나, 이미 존재하는 경우 그 참조를 반환합니다. 결과적으로 str1str4는 동일한 참조를 가리키게 됩니다. 주의! 그러나 str3str4는 다른 참조를 가리킨다.

        활용 사례

      • 메모리 최적화: 문자열이 자주 생성되고 사용되는 애플리케이션에서 메모리 사용을 줄이기 위해 사용됩니다. 동일한 문자열은 상수 풀에서 공유되므로 메모리 낭비를 줄일 수 있습니다.

      • 문자열 비교 성능: 문자열 비교 시 equals 메서드를 사용하면 내용 비교를 위해 문자열의 모든 문자를 확인해야 합니다. 하지만 intern()을 사용하여 문자열을 비교하면, 참조 비교(==)로 동일성을 확인할 수 있어 성능이 향상됩니다.

        주의 사항

      • 과도한 사용: 모든 문자열에 intern()을 남용하면 상수 풀에 불필요한 문자열이 많이 쌓일 수 있어 오히려 메모리 사용이 증가할 수 있습니다. 따라서 필요한 경우에만 사용해야 합니다.

      • JVM의 메모리 관리: 문자열 상수 풀은 JVM에 의해 관리되므로, 풀의 크기나 관리 방식은 JVM 구현에 따라 다를 수 있습니다. Java 7 이후부터는 상수 풀이 힙(heap) 메모리로 옮겨져 힙 크기에 영향을 받습니다.

        intern() 메서드는 문자열의 메모리 사용을 최적화하고 문자열 비교 성능을 향상시키는 유용한 도구이지만, 올바른 사용이 중요합니다. 필요할 때 적절히 사용하는 것이 좋습니다.

  • 스트링 객체의 주요 특징
    • 주의! 스트링 객체는 수정 불가능(immutable)하다. Untitled Untitled
      • String 조작 함수는 String객체를 직접적으로 수정하는 것이 아닌 새로운 String 객체를 만들어서 리턴하는 것이다.
      • return형이 String인 함수 모두 원본은 변경시키지 않으니 주의할 것
      • 만약, String 객체를 수정하고 싶다면 원본으로 함수의 리턴을 받아야함 ex) s=s.concat(”Java”);
      • char형 배열처럼 다룰 수 없음! 인덱스 별 수정등 직접적으로 변경이 불가능하다.
    • 스트링의 내용 비교 시 반드시 equals()를 사용
      • ==은 레퍼런스 값을 비교한다
      • equals()는 내용을 비교한다

중요 문자열 활용

  • 중요 String 주요 메소드 Untitled
  • 문자열 비교
    • int compareTo(String anotherString)
      • 문자열이 같으면 0을 리턴함
      • 이 문자열이 another보다 사전에 먼저 나오면 음수 리턴
      • 이 문자열이 another보다 사전에 나중에 나오면 양수 리턴 Untitled
    • Comparable 인터페이스: 자바에서 객체의 순서를 정의하기 위해 사용된다. 클래스에서 Comparable 인터페이스를 구현하면 객체를 정렬할 때, compareTo메소드를 오버라이딩하여 사용하게 된다.
      • 상위 클래스로 하위 클래스를 받을 수 있듯이 Comparabe이 인자로 왔을 때, 해당 클래스도 인자로 받도록 해준다.
      • String 클래스는 Comparable 인터페이스를 구현하고 있다. 따라서 String객체는 compareTo 메소드를 통해 비교할 수 있다.
  • 문자열 연결
      • 연산자로 문자열 연결
        • 피연산자에 문자열이나 객체가 포함되어 있는 경우
          • 객체는 객체.toString()을 호출하여 문자열로 변환하여 연결

          • 기본 타입 값은 문자열로 변환하여 연결

            Untitled

    • String concat(String str)을 이용한 문자열 연결
      • 기존 String 객체에 연결되지 않고 새로운 String 객체를 리턴한다
      • 주의! String 리터럴에도 사용할 수 있음 Untitled Untitled
  • 문자열 내의 공백 제거
    • String trim()
      • 문자열 앞 뒤 공백 제거
        • 문자열 앞 뒤 공백 문자(tab, enter, space) 제거한 문자열 리턴

          Untitled

  • 문자열의 각 문자 접근

    • char charAt(int index)
      • 각 문자 접근
        • 문자열 내의 각각의 인덱스에 위치한 문자에 접근 Untitled Untitled
  • 문자열 분할하여 배열에 저장

    • 문자열을 입력한 regex(Regular Expression)문자를 기준으로 분할하여 배열에 저장함
      • String[] split(String regex) String input =*scanner*.nextLine(); String[] location = input.split(",");//”,” 기준으로 분할
      • 주의! 공백을 regex에 같이 사용하고 싶으면 “,\s*”를 입력해야함 그러나 무조건 공백이 있어야되기때문에 가용성이 떨어짐
      • ,을 regex로 입력받은 뒤에 trim()을 사용하면 ,로 구분되어 입력된 문자열들을 배열로 저장할 수 있다. cityName=location[0].trim(); lon=Integer.*parseInt*(location[1].trim()); lat=Integer.*parseInt*(location[2].trim());
  • 문자열의 포함 여부

    • boolean contains(CharSequence s)
      • 공백과 대소문자 등을 구분하여 정확히 매개변수로 받은 문자열을 가지는 지 검사한다.
      • 내부적 작동원리는 indexOf()의 메소드 결과가 -1인지를 검사하는 것이다. (indexOf()는 매개변수로 받은 문자열이 처음으로 등장하는 위치를 반환한다. 문자열이 존재하지 않으면 -1을 반환한다)
  • 문자열을 대체

    • String replace(char oldChar, char newChar)
    • String replace(CharSequence target, CharSequence replacement)
      • 위의 형식대로 문자열 중 특정 문자만 새로운 문자로 대체하거나 문자열 중 특정 문자열을 새로운 문자열로 대체한다
  • 문자열의 부분 문자열

    • String substring(int beginIndex)
    • String substring(int beginIndex, int endIndex)
      • 위의 형식대로 문자열 중 시작 인덱스부터 끝까지의 부분 문자열을 리턴하거나 시작 인덱스부터 끝 인덱스-1까지의 부분 문자열을 리턴한다.

문자열 활용 예제

public class StringEx {
    public static void main(String[] args) {
        String a = new String(" C#");
        String b = new String(",C++ ");

        System.out.println(a + "의 길이는 "+ a.length());
        System.out.println(a + "는 \"#\"을 가지고 있다: " + a.contains("#"));

        a = a.concat(b);
        System.out.println(a);

        a = a.trim();
        System.out.println(a);

        a=a.replace("C#", "Java");
        System.out.println(a);

        String s[] = a.split(",");
        for(int i=0;i<s.length;i++){
            System.out.println("분리된 문자열"+i+": "+s[i]);
        }
        a = a.substring(5);
        System.out.println(a);

        char c = a.charAt(2);
        System.out.println(c);
    }
}

출력 결과:

C#의 길이는 3
C#는 "#"을 가지고 있다: true
C#,C++
C#,C++
Java,C++
분리된 문자열0: Java
분리된 문자열1: C++
C++

Untitled

  • 주의! 문자열의 수정이 아닌 새로운 문자열 객체를 가리킨다는 것

문자열을 다루는 여러 클래스와 인터페이스

자바에서 문자열을 다루는 여러 클래스와 인터페이스가 존재합니다. 각각의 특징과 사용법을 간단히 설명하겠습니다.

String

String 클래스는 불변(immutable) 문자열을 나타냅니다. String 객체는 생성 후 변경할 수 없습니다.

주요 특징

  • 불변성: String 객체는 한 번 생성되면 수정할 수 없습니다. 모든 수정 작업은 새로운 String 객체를 생성합니다.
  • 문자열 리터럴: "Hello"와 같은 문자열 리터럴은 String 객체로 취급됩니다.
  • 내장 메서드: 문자열 조작을 위한 다양한 메서드를 제공합니다 (예: substring(), replace(), toLowerCase() 등).

예제 코드

java코드 복사
public class StringExample {
    public static void main(String[] args) {
        String str = "Hello, world!";
        String upperStr = str.toUpperCase();
        System.out.println(upperStr); // HELLO, WORLD!
    }
}

StringBuffer

StringBuffer 클래스는 가변(mutable) 문자열을 나타냅니다. 문자열의 내용을 변경할 수 있으며, 멀티스레드 환경에서 안전하게 사용할 수 있습니다.

주요 특징

  • 가변성: 문자열을 변경할 수 있습니다.
  • 스레드 안전성: 모든 메서드는 동기화되어 있어 멀티스레드 환경에서 안전하게 사용할 수 있습니다.
  • 성능: StringBuilder보다 성능이 떨어지지만, 스레드 안전성이 필요할 때 유용합니다.

예제 코드

java코드 복사
public class StringBufferExample {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        sb.append(", world!");
        System.out.println(sb.toString()); // Hello, world!
    }
}

StringBuilder

StringBuilder 클래스는 StringBuffer와 유사하지만, 스레드 안전성을 제공하지 않습니다. 단일 스레드 환경에서 더 높은 성능을 제공합니다.

주요 특징

  • 가변성: 문자열을 변경할 수 있습니다.
  • 스레드 안전성 없음: 멀티스레드 환경에서 안전하지 않습니다.
  • 성능: 스레드 안전성이 필요하지 않은 경우 StringBuffer보다 성능이 좋습니다.

예제 코드

java코드 복사
public class StringBuilderExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello");
        sb.append(", world!");
        System.out.println(sb.toString()); // Hello, world!
    }
}

StringTokenizer

StringTokenizer 클래스는 문자열을 구분자를 기준으로 분리하는 데 사용됩니다. 자바 1.4 이후로는 String.split() 메서드를 더 많이 사용하지만, 여전히 유용할 수 있습니다.

주요 특징

  • 분리: 문자열을 구분자로 분리하여 토큰화합니다.
  • 사용법: 공백을 기본 구분자로 사용하며, 다른 구분자를 지정할 수도 있습니다.

예제 코드

java코드 복사
import java.util.StringTokenizer;

public class StringTokenizerExample {
    public static void main(String[] args) {
        StringTokenizer st = new StringTokenizer("Hello, world!", ", ");
        while (st.hasMoreTokens()) {
            System.out.println(st.nextToken());
        }
        // Output:
        // Hello
        // world!
    }
}

중요 CharSequence

CharSequence는 문자열을 읽기 위한 인터페이스로, String, StringBuffer, StringBuilder 등이 이를 구현합니다. 여러 문자열 클래스를 일관되게 다룰 수 있습니다.

주요 특징

  • 추상화: 여러 종류의 문자열 클래스를 추상화하여 다룰 수 있습니다.
  • 주요 메서드: length(), charAt(int index), subSequence(int start, int end) 등을 제공합니다.

예제 코드

java코드 복사
public class CharSequenceExample {
    public static void main(String[] args) {
        CharSequence cs = "Hello";
        System.out.println(cs.length()); // 5
        System.out.println(cs.charAt(1)); // e
    }
}

요약

  • String: 불변 문자열을 나타냅니다. 문자열 리터럴을 포함한 대부분의 문자열 작업에 사용됩니다.
  • StringBuffer: 가변 문자열을 나타내며, 멀티스레드 환경에서 안전합니다.
  • StringBuilder: 가변 문자열을 나타내며, 단일 스레드 환경에서 높은 성능을 제공합니다.
  • StringTokenizer: 문자열을 구분자로 분리하는 데 사용됩니다. 자바 1.4 이후로는 String.split()을 더 많이 사용합니다.
  • CharSequence: 문자열을 읽기 위한 인터페이스로, 여러 문자열 클래스를 일관되게 다룰 수 있습니다.

이러한 클래스를 활용하여 다양한 문자열 처리 작업을 효율적으로 수행할 수 있습니다.

중요 StringBuffer 클래스

  • StringBuffer 클래스: 중요 가변 문자열(길이, 문자열 muttable) 저장 클래스

    • java.lang.StringBuffer
    • String 클래스와 달리 문자열 변경 가능
    • StringBuffer 객체의 크기는 스트링 길이에 따라 가변적
      • 문자열을 몇차례 조작할 경우 String대신 StringBuffer를 사용한다! 사용하다가 toString()으로 옮겨주면 된다.
        • String s = sb.toString();
    • StringBuilder와 쌍둥이 클래스이다. 차이는 StringBuffer는 동기화를 지원하여 멀티플 쓰레드에서 안정적이지만, StringBuilder는 동기화를 보장하지 않아서 싱슬 쓰레드에서 사용한다.
  • StringBuffer 클래스의 생성자

    Untitled

Untitled

  • StringBuffer의 주요 메소드 Untitled
    • 중요 StringBuffer의 메소드는 실행 시 muttable하게 문자열의 값이 수정됨을 알 수 있다.
    • 주의!
      • capacity는 용량을 말하고 length는 실제 저장된 문자수를 말함

      • insert의 offset의 인덱스 다음위치가 아닌 정확히 offset의 위치에 삽입한다! offset의 위치에 있던 문자는 삽입한 문자열 뒤에 위치하게 됨

      • replace는 start부터 end-1인덱스 만큼을 삭제하고 그 위치에 str을 넣어준다고 생각하면 된다.

      • setLength에서 문자열의 길이를 재설정할 때, 작은 경우에 기존 문자열이 잘리는 것을 주의하기! 만약 현재길이보다 길다면 ‘\u0000’( null )로 채워져서 출력함

        → 인덱스 0부터 세는 것에 항상 주의할 것!!!

  • StringBuffer의 메소드 활용 예 Untitled

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");
        System.out.println(sb);

        sb.replace(8,10,"your");
        System.out.println(sb);

        sb.delete(8,13);
        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주의! import해주어야 사용 가능하다!!

    • 하나의 문자열을 여러 문자열로 분리하고 분리된 문자열을 토큰이라 부른다
      • 문자열을 분리할 때 사용되는 기준 문자를 통해 구분한다.
      • 구분문자(delimiter)를 생성자에 같이 넣어주게 된다.
        • 주의! 구분문자는 String으로 넣어줘야함
      • 토큰을 나누어 객체안의 멤버로 가진다 (연결리스트) Untitled
      • String클래스의 split()과 동일한 역할을 하기 때문에 동일한 구현 가능
  • StringTokenizer 객체 생성과 문자열 분리

    Untitled

    • 주의! 구분문자에 넣어준 문자는 따로따로 각각의 문자가 구분자가 된다! 구분자가 들어있는 공간을 기준으로 구분해준다고 생각하면 된다! (여러 구분자가 겹쳐있어도 한 구분자로 침)
  • StringTokenizer 클래스의 생성자

    Untitled

    • 기본 구분자 사용 (공백)
      StringTokenizer st = new StringTokenizer(str);
      • 기본 구분자인 공백으로 문자열을 분리합니다.
      • This, is, a, sample, string이라는 토큰이 생성됩니다.
    • 지정된 구분자 사용 (콤마)
      StringTokenizer st2 = new StringTokenizer(str2, delimiter);
      • 콤마(,)를 구분자로 문자열을 분리합니다.
      • apple, banana, cherry, date라는 토큰이 생성됩니다.
    • 구분자를 토큰에 포함
      StringTokenizer st3 = new StringTokenizer(str3, delimiter2, true);
      • 콜론(:)을 구분자로 사용하되, 구분자를 토큰에 포함합니다.
      • one, :, two, :, :, three, :, four라는 토큰이 생성됩니다.
  • StringTokenizer의 주요 메소드

    Untitled

    • while문에 hasMorTokens()를 걸어주고 nextToken()을 통해 다음 토큰을 리턴한다. → 처음에 nextToken()을 사용해주면 첫 Token이 튀어나온다.

StringTokenizer 클래스 메소드 활용 예시

import java.util.StringTokenizer;

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

출력 결과:

홍길동
장화
홍련
콩쥐
팥쥐

Math 클래스

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

      Untitled

  • Math 클래스를 활용한 난수 발생
    • static double random()
      • 0.0이상 1.0미만의 임의의 double 값을 반환
      • 0에서 100사이의 난수 10개를 발생시키는 예시 Untitled
        • Math.random()*100은 0.0~99.99. 사이의 실수 리턴
        • Math.random()*100+1은 1.0~100.99. 사이 실수 값
        • (int)(Math.random()*100+1)는 소수점 이하를 제거하여 1~100 사이의 정수 값을 나타냄
        • (int)(Math.random()*m+n)은 [n,m]의 정수 값을 나타냄
    • java.util.Random 클래스로 다양한 타의 난수를 발생시킬 수도 있음

Math 클래스 메소드 활용 예시

Untitled

Calendar 클래스

  • java.util.Calendar: 시간과 날짜 정보 저장 및 관리
    • 년, 월, 일, 요일, 시간, 분, 초, 밀리초, 오전 오후 등
    • Calendar 클래스의 각 시간 요소를 설정하거나 알아내기 위한 필드 Untitled
      • 주의! 달과 시간은 0~11로 인덱스처럼 -1씩 적용됨!
  • Calendar 객체 생성 및 날짜와 시간
    • Calendar 객체 생성
      • Calendar now = Calendar.getInstance();
        • now 객체는 getInstance()메소드를 통해 현재 날짜와 시간 정보를 가지고 생성
        • 주의! Calendar는 추상 클래스이므로 new Calendar()를 하지 않음
      • 날짜와 시간 알아내기 Untitled
      • 날짜와 시간 설정하기 Untitled
        • 주의! Calendar 객체에 날짜와 시간을 저장한다고 컴퓨터의 날짜와 시간을바꾸는 것은 아님
        • set(int field, int value) 메소드이나 set(년, 월, 일)은 예외적으로 허용됨

Calendar를 이용하여 현재날짜와 시간 알아내고 설정하기

Untitled

  • (Calendar레퍼런스).get(Calandar.필드)로 값을 얻는다

원본 노션 링크

https://believed-poinsettia-f0f.notion.site/6-3decc5b1dbfe4c96b9c3512008ee4498?pvs=4

0개의 댓글