1. 문자열과 char

  • String은 수정할 수 없음 → StringBuilder 사용
char ch = 'A';
String str = "Apple";

str.length(); // 5
str.charAt(2); // p
str.substring(1, 3); // pp: 1번부터 2번까지
str.contains("pp"); // true
str.toLoserCase() // apple

// 모든 문자 하나씩 확인
for (int i = 0; i < text.length(); i++) {
    char ch = text.charAt(i);
    System.out.println(ch);
}

// 문자열 내용 비교 vs 객체 비교
String a = new String("java");
String b = new String("java");

System.out.println(a.equals(b)); // true: 내용이 같음
System.out.println(a == b);      // false: 서로 다른 객체

int number = Integer.parseInt("123");
String text = String.valueOf(123); // toString대신 null값 처리 가능

2. BufferedReader

  • 입력을 한 줄씩 읽는 도구
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

String line = br.readLine();

// 숫자로 변환
int age = Integer.parseInt(br.readLine());

// 전체 기본 구조
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br =
                new BufferedReader(new InputStreamReader(System.in));

        int number = Integer.parseInt(br.readLine());
        System.out.println(number + 1);
    }
}

3. StringTokenizer

  • 문자열을 공백 같은 구분자를 기준으로 나누는 도구
  • br이 한 줄을 읽고, st가 그 줄을 나누는 형식
StringTokenizer st = new StringTokenizer("10 20 30");

int a = Integer.parseInt(st.nextToken()); // 10
int b = Integer.parseInt(st.nextToken()); // 20
int c = Integer.parseInt(st.nextToken()); // 30

// 입력: 10 20
StringTokenizer st = new StringTokenizer(br.readLine());

int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());

// 조각 개수 모를 때
while (st.hasMoreTokens()) {
    System.out.println(st.nextToken());
}

4. StringBuilder

  • 문자열을 수정, 연결할 때
StringBuilder sb = new StringBuilder();

sb.append("hello");
sb.append(" ");
sb.append("java");

String result = sb.toString(); // "hello java"

// 자주 쓰는 기능
StringBuilder sb = new StringBuilder("abcd");

sb.append("e");       // "abcde"
sb.setCharAt(0, 'A');  // "Abcde"
sb.deleteCharAt(1);    // "Acde"
sb.reverse();         // "edcA"
sb.length();          // 4

// 반복문으로 한 글자씩 출력
for (int i = 1; i <= 3; i++) {
    sb.append(i).append('\n');
}

5. ArrayList

  • 크기가 자동으로 늘어나는 배열 같은 자료구조
  • 일반 배열은 만들 때 크기를 정함
  • ArrayList는 원소를 추가하면서 크기가 늘어남
// 일반 배열
int[] arr = new int[3];

// ArrayList
ArrayList<Integer> list = new ArrayList<>();

list.add(10);
list.add(20);
list.add(30);

// 사용 가능한 메소드
list.get(0);      // 10: 조회
list.set(1, 99);  // [10, 99, 30]: 변경
list.remove(0);   // [99, 30]: 0번 원소 삭제
list.size();      // 2: 원소 개수
list.isEmpty();   // false
list.contains(99); // true

// 정수리스트 원소 삭제
list.remove(1);                  // 1번 인덱스 삭제
list.remove(Integer.valueOf(99)); // 값이 99인 첫 원소 삭제

6. HashMap

  • 키와 값을 짝지어 저장하는 자료구조
  • 키는 중복되지 않아서 같은 키로 다시 저장하면 값이 바뀜
HashMap<String, Integer> scores = new Hashmap<>();

scores.put("민수", 90);
scores.ut("영희", 85);

scores.get("민수"); // 90

scores.put("민수", 100);
scores.get("민수"); // 100

// 자주 쓰는 기능
scores.containsKey("민수");     // true
scores.getOrDefault("영희", 0); // 없으면 0
scores.remove("지수");          // 해당 키와 값 삭제
scores.size();                 // 저장된 쌍의 개수

// 코테에서는 등장 횟수 세기에 자주 사용
String[] fruits = {"apple", "banana", "apple"};

HashMap<String, Integer> counts = new HashMap<>();

for (String fruit : fruits) {
    counts.put(fruit, counts.getOrDefault(fruit, 0) + 1);
}

// apple → 2
// banana → 1

// 전체 순회
for (String key : counts.keySet()) {
    System.out.println(key + ": " + counts.get(key));
}

7. HashSet

  • 중복 없이 값만 저장
HashSet<Integer> set = new HashSet<>();

set.add(10);
set.add(20);
set.add(10);

System.out.println(set.size()); // 2

// 10을 2번 넣어도 1번만 저장됨
set.contains(10); // true
set.remove(20);   // 20 삭제
set.isEmpty();    // false

 

이름별 점수, 단어별 개수 HashMap
중복 제거, 이미 등장했는지 확인 HashSet

8. ArrayDeque

  • 앞 뒤 양쪽에서 원소를 넣고 뺄 수 있는 자료구조
  • 큐: BFS 같은 탐색에서 사용
  • 스택: 괄호 검사, 최근 작업 처리 등에 사용
  • peek: 확인만 함
  • poll/pop: 꺼내면서 삭제
  • 빈 상태에서 pollFirst()는 널 반환, pop은 예외 발생
// 큐로 사용하면 먼저 들어간 것이 먼저 나옴
ArrayDeque<Integer> deque = new ArrayDeque<>();

deque.offerFirst(10); // [10]
deque.offerLast(20);  // [10, 20]
deque.offerFirst(5);  // [5, 10, 20]

deque.peekFirst();   // 5: 앞 조회
deque.peekLast();    // 20: 뒤 조회
deque.pollFirst();   // 5를 꺼내고 삭제
deque.pollLast();    // 20을 꺼내고 삭제

// 스택으로 사용하면 나중에 들어간 것이 먼저 나옴
ArrayDeque<Integer> stack = new ArrayDeque<>();

stack.push(10);
stack.push(20);

stack.pop(); // 20
stack.pop(); // 10

9. PriorityQueue

  • 우선순위가 높은 원소부터 꺼냄
  • 정수는 기본적으로 작은 수부터
  • 큰 수부터로 바꾸고 싶으면 Comparator.reverseOrder()
PriorityQueue<Integer> pq = new PriorityQueue<>();

pq.offer(30);
pq.offer(10);
pq.offer(20);

pq.peek(); // 10: 확인만 함

pq.poll(); // 10
pq.poll(); // 20
pq.poll(); // 30

PriorityQueue<Integer> pq =
        new PriorityQueue<>(Comparator.reverseOrder());

10. sort

배열 Arrays.sort()
ArrayList 같은 리스트 Collections.sort()
// 배열 정렬
int[] arr = {30, 10, 20};

Arrays.sort(arr);
// arr: [10, 20, 30]

// 리스트 정렬
ArrayList<Integer> list = new ArrayList<>();

list.add(30);
list.add(10);
list.add(20);

Collections.sort(list);
// list: [10, 20, 30]

11. Comparator

  • 정렬 기준을 직접 정하는 도구
    • 오름차순/내림차순
    • 문자열 길이 순..
Collections.sort(list, Comparator.reverseOrder()); // 내림차순

// 문자열 길이 순
String[] words = {"banana", "cat", "apple"};

Arrays.sort(
    words,
    (a, b) -> Integer.compare(a.length(), b.length())
);

// ["cat", "apple", "banana"]

 

'전공 > Java' 카테고리의 다른 글

[JAVA] Maven 프로젝트 톰캣 실행 오류 정리  (0) 2026.07.20

이클립스(Eclipse) 환경에서 내장 Apache Tomcat 9.0을 연동하여 자바 표준 웹소켓(JSR-356) 및 org.json 라이브러리 기반의 전자봉투 암호화 서비스를 구축하는 과정에서 발생한 5가지 핵심 빌드/런타임 에러와 그 해결법에 대한 정리입니다.

1. Tomcat 7 v.s. Java 최신 바이트코드 충돌 에러

[현상]

Maven Plugin(tomcat7-maven-plugin:run)으로 가동 시 콘솔에 아래와 같은 치명적 예외가 출력됨.

SEVERE: Unable to process Jar entry [META-INF/versions/9/module-info.class] from Jar [...]
org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19

[원인]

Tomcat 7 버전에 내장된 오래된 바이트코드 컴파일러 스캔 모듈(BCEL)이, 최신 Java 규격(Java 9 이상 Multi-Release JAR) 및 최신 라이브러리(json-20240303.jar) 내부에 포함된 module-info.class 구조를 해석하지 못해 컴파일 형식을 오인한 것입니다.

[해결법]

외부 플러그인 구동 방식을 배제하고, Java 최신 스펙을 정상 지원하는 Tomcat 8.5 또는 Tomcat 9.0 메인 엔진을 이클립스 내장 서버 제어(WTP) 환경에 직접 연동하는 표준 방식으로 전환해야 합니다.

2. Project Facets 메뉴 누락 및 Java EE 버전 불일치

[현상]

이클립스 프로젝트 속성(Properties) 창에서 웹 프로젝트 설정을 위한 Project Facets 메뉴가 보이지 않거나, 설정 시 Tomcat version 9.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5, 6, 7, and 8 Web modules 제약 메시지가 발생함.

[원인]

  • 메이븐 기본 빌드 포맷이 일반 자바 애플리케이션(jar)으로 지정되어 있어 이클립스가 구조를 오인함.
  • Dynamic Web Module 규격을 Tomcat 9.0의 최대 수용 사양인 Java EE 8 (Servlet 4.0)을 초과하여 Jakarta EE 규격(5.0 이상)으로 선택했을 때 발생하는 정적 버전 충돌입니다.

[해결법]

  1. pom.xml 최상단에 웹 아카이브 빌드 지시어를 명시합니다.
  2.  
    <packaging>war</packaging>
    
  3. 프로젝트 우클릭 -> Properties -> Project Facets 메뉴에서 Dynamic Web Module 버전을 4.0으로 하향 조정하고, Java 컴파일러 버전을 로컬 JDK 사양(예: 11 또는 17)과 일치시킵니다.

3. Bootstrap 클래스 로드 실패 예외 (ClassNotFoundException)

[현상]

톰캣 서버 실행 시 기동 시점에 메인 스레드가 다운됨.

Exception in thread "main" java.lang.ClassNotFoundException: org.apache.catalina.startup.Bootstrap

[원인]

이클립스 서버 런타임 설정이 꼬이면서 톰캣 가동의 최우선 진입점 파일인 bin/bootstrap.jar 경로 인덱스를 Java 가상 머신(JVM)의 Classpath 인자가 잃어버렸기 때문입니다.

[해결법]

  1. Run -> Run Configurations... ->  Apache Tomcat 트리 내부의 인스턴스를 선택합니다.
  2. Classpath 탭으로 이동하여 User Entries를 마우스로 선택합니다.
  3. Add External JARs... 버튼을 눌러 실제 Tomcat 설치 폴더의 bin/ 디렉토리 내부에서 아래 3가지 핵심 Core 파일을 수동으로 찾아 등록합니다.
    • bootstrap.jar
    • tomcat-juli.jar
    • commons-daemon.jar

4. Catalina 클래스 로드 예외 및 이클립스 내부 경로 꼬임

[현상]

Bootstrap은 찾았으나 연이어 엔진 초기화 실패 예외가 발생함.

경고: Problem with directory [.../eclipse/lib], exists: [false]
심각: Init exception
java.lang.ClassNotFoundException: org.apache.catalina.startup.Catalina

[원인]

톰캣 컨테이너가 구동될 때 자사 엔진 파일들을 참조할 마스터 홈 경로 파라미터인 catalina.home과 catalina.base가 실제 톰캣 설치 폴더가 아닌 이클립스 프로그램 실행 폴더로 잘못 오인되어 라이브러리 스캔 범위가 이탈한 것입니다.

[해결법]

  1. Run Configurations... 설정 창의 Arguments 탭으로 이동합니다.
  2. VM arguments 입력란 맨 뒤에 한 칸을 띄우고, 실제 Tomcat 물리 경로 파라미터를 다음과 같이 강제 주입합니다.
  3. Plaintext
     
    -Dcatalina.home="D:/apache-tomcat-9.0.100" -Dcatalina.base="D:/apache-tomcat-9.0.100"
    
  4. 하단의 Working directory를 Default에서 Other로 체크 변경한 뒤, 실제 Tomcat 최상위 설치 폴더 경로를 명시해 줍니다.

5. 웹소켓 처리 시 JSONObject 클래스 미발견 예외 (NoClassDefFoundError)

[현상]

화면(HTTP) 진입은 성공하고 웹소켓 커넥션(ws://...) 핸드셰이크 요청까지 도달했으나, 패킷이 인입되는 순간 서버 채널이 강제로 끊어지며 자바 콘솔에 아래 에러가 출력됨.

[웹소켓 에러 발생] 사유: java.lang.NoClassDefFoundError: org/json/JSONObject
[시스템 정보] 클라이언트 세션 커넥션 닫힘

[원인]

pom.xml 파일에 org.json 의존성이 올바르게 정의되어 컴파일은 성공했으나, 이클립스 WTP 내부의 배포 어셈블리(Deployment Assembly) 명세서에 메이븐 의존성 항목이 누락된 상태입니다. 이로 인해 톰캣 가동용 런타임 가상 디렉토리인 WEB-INF/lib/ 폴더 내부로 json-20240303.jar 파일이 물리적으로 복사되지 않아 발생한 자바 전형적인 런타임 예외입니다.

[해결법]

  1. 프로젝트 우클릭 ->  Properties로 진입합니다.
  2. 왼쪽 메뉴에서 Deployment Assembly 탭을 선택합니다.
  3. 우측 메뉴 바에서 Add... 버튼을 클릭합니다.
  4. Java Build Path Entries를 선택하고 Next를 누른 뒤, 목록에서 Maven Dependencies를 선택하고 Finish를 누릅니다.
  5. 소스 목록에 Maven Dependencies가 추가되고 이의 배포 경로(Deploy Path)가 WEB-INF/lib로 안전하게 바인딩된 것을 확인한 뒤 서버를 리스타트합니다.

'전공 > Java' 카테고리의 다른 글

[JAVA] 기본 문법 정리  (0) 2026.10.22

+ Recent posts