문자열
- 1. [Java] 암호 해독 - cipher.charAt(i - 1)
- 2. [Java] 대문자와 소문자
- 3. [Java] 영어가 싫어요 - numbers.replaceAll(a,b);
- 4. [Java] 인덱스 바꾸기 - return new String(arr);
- 5. [Java] 한 번만 등장한 문자 (문자열) - sb.toString();
- 10. [Java] 숫자 찾기 - String.indexOf(), String.valueOf()
1. [Java] 암호 해독 - cipher.charAt(i - 1)
https://school.programmers.co.kr/learn/courses/30/lessons/120892
오답
class Solution {
public String solution(String cipher, int code) {
StringBuilder sb = new StringBuilder();
for (int i = code; i <= cipher.length(); code++;) {
sb.append(cipher[i-1]); // 인덱스는 0부터 시작
}
return sb.toString();
}
}
✅ for문의 증가식 오류
for (int i = code; i <= cipher.length(); code++;)
- → code++→ 증가식 자리에 있어야 할 변수는 i (반복 제어 변수)
- → code++는 code 값을 계속 바꿔버려서 논리적으로도 틀림
✅ 문자열 인덱스 접근 오류
- Java에서 문자열은 []로 접근 불가 → charAt(index) 사용해야 함
정답 코드
class Solution {
public String solution(String cipher, int code) {
StringBuilder sb = new StringBuilder();
for (int i = code; i <= cipher.length(); i += code) {
sb.append(cipher.charAt(i - 1)); // 인덱스는 0부터 시작
}
return sb.toString();
}
}
2. [Java] 대문자와 소문자
https://school.programmers.co.kr/learn/courses/30/lessons/120893
오답
class Solution {
public String solution(String my_string) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < my_string.length(); i++) {
if(Character.isUpperCase((my_string.charAt(i)))) {
sb.append(Character.toLowerCase(my_string.charAt(i)));
} else {
sb.append(Character.toUpperCase(my_string.charAt(i)));
}
}
return sb.toString();
}
}
✅ my_string.charAt(i)는 위로 빼서 char c = my_string.charAt(i); 로 만들어 주면 코드가 간단해진다.
개선한 코드
class Solution {
public String solution(String my_string) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < my_string.length(); i++) {
char c = my_string.charAt(i);
if(Character.isUpperCase(c)) {
sb.append(Character.toLowerCase(c));
} else {
sb.append(Character.toUpperCase(c));
}
}
return sb.toString();
}
}
3. [Java] 영어가 싫어요 - numbers.replaceAll(a,b);
https://school.programmers.co.kr/learn/courses/30/lessons/120894
틀린 코드
class Solution {
public long solution(String numbers) {
String[] words = {
"zero", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine"
};
for (int i = 0; i < words.length; i++) {
numbers = numbers.replace(words[i], String.valueOf(i));
}
return Integer.parseInt(numbers);
}
}
테스트는 통과했으나 답안 제출시 런타임 에러
✅ Integer.parseInt() 사용 시 런타임 에러
- 만약 숫자 문자열이 int의 범위를 초과하면 런타임 에러가 발생한다.
- 그래서 일부 테스트 케이스에서 에러가 난 것
- 예를 들어서, 만약 13자리 숫자가 들어오면 int(32비트 정수)의 최대값 2,147,483,647을 초과함
- → Integer.parseInt()는 처리 못 함 → 런타임 에러 (NumberFormatException) 발생
- 따라서 return 타입을 int가 아니라 long 타입으로 변경해야 한다.
개선한 코드
class Solution {
public long solution(String numbers) {
String[] words = {
"zero", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine"
};
for (int i = 0; i < words.length; i++) {
numbers = numbers.replaceAll(words[i], String.valueOf(i));
}
return Long.parseLong(numbers); // ✅ int → long 으로 변경
}
}
기본형 VS 래퍼클래스
✅ 기본형 (Primitive type)
- int → 기본형 정수 타입 (primitive int)
- long → 기본형 정수 타입 (primitive long)
👉 메모리에 값 자체를 저장함
👉 성능이 빠르고 메모리 사용이 효율적
✅ 참조형 (Reference type, Wrapper class)
- Integer → 참조형 (래퍼 클래스, Wrapper class for int)
- Long → 참조형 (래퍼 클래스, Wrapper class for long)
👉 객체이기 때문에 null 값을 가질 수 있음
👉 ArrayList<Integer>처럼 제네릭에 사용 가능
👉 기본형은 제네릭에서 사용할 수 없음 → 참조형 필요
4. [Java] 인덱스 바꾸기 - return new String(arr);
https://school.programmers.co.kr/learn/courses/30/lessons/120895
틀린 코드
class Solution {
public String solution(String my_string, int num1, int num2) {
String[] arr = String.toCharArray(my_string);
char tmp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = tmp;
return arr.toString();
}
}
✅ String[] arr = String.toCharArray(my_string);
- → String.toCharArray()는 char[]를 리턴하므로 타입은 String[]이 아니라 char[]이어야 한다.
✅ String.toCharArray() 용법
- → my_string.toCharArray();
- toCharArray()는 String 클래스의 인스턴스 메서드이다.
- 그래서 String.toCharArray() ❌ (클래스 메서드 아님)
- 반드시 인스턴스(my_string)에 붙여야 한다.
✅ return arr.toString();
- char[]에서 toString()을 쓰면 주소값이 출력된다.
- → 대신 new String(arr)을 사용해야 문자열로 출력된다.
개선한 코드
class Solution {
public String solution(String my_string, int num1, int num2) {
char[] arr = my_string.toCharArray();
char tmp = arr[num1];
arr[num1] = arr[num2];
arr[num2] = tmp;
return new String(arr);
}
}
클래스 메서드 VS 인스턴스 메서드
자바에서 메서드는 크게 인스턴스 메서드와 **클래스 메서드(static 메서드)**로 나뉘는데, 이 둘은 메서드를 어떻게 호출하고 언제 사용하는지에 따라 중요한 차이를 가진다.
클래스 메서드는 static 키워드로 정의되어 있어 객체를 만들지 않아도 클래스 이름으로 바로 호출할 수 있는 메서드이다. 클래스 메서드는 객체의 고유 상태와는 무관하며, 보통 모든 인스턴스에서 공통으로 사용하는 로직을 구현할 때 사용됩니다. 대표적인 예로 Integer.parseInt("123")는 문자열을 정수로 변환하는 클래스 메서드로, Integer라는 클래스 이름만으로 바로 호출할 수 있다.
반면 인스턴스 메서드는 특정 객체가 생성되어야만 사용할 수 있는 메서드이다. 즉, new 키워드로 객체를 만든 후에야 호출이 가능하며, 주로 그 객체의 상태(멤버 변수)를 기반으로 동작한다. 예를 들어, str.length()는 문자열 객체 str의 길이를 반환하는 인스턴스 메서드인데, 이는 str이라는 객체가 존재해야만 호출할 수 있다.
인스턴스 메서드는 객체마다 상태가 다를 수 있기 때문에, 같은 메서드를 호출하더라도 객체에 따라 결과가 달라진다. 예를 들어, Person이라는 클래스에 sayHello()라는 인스턴스 메서드가 있다면, person1.sayHello()와 person2.sayHello()는 각각 다른 이름을 출력한다. 이는 각 인스턴스가 가지고 있는 name 값이 다르기 때문이다.
이처럼 인스턴스 메서드는 객체의 고유한 데이터를 다루고 조작할 때 유용하며, 클래스 메서드는 그와 무관한 공통 기능을 제공할 때 사용된다. 개발자는 기능의 목적에 따라 두 메서드 중 적절한 쪽을 선택해야 한다. 객체마다 달라지는 동작이 필요하다면 인스턴스 메서드, 객체 없이 호출해도 되는 범용적인 기능이라면 클래스 메서드를 사용하는 것이 좋다.
✅ 1. 인스턴스 메서드 (Instance Method)
정의
- 객체를 생성해야 호출할 수 있는 메서드
- 객체의 상태(필드 값)에 따라 동작이 달라질 수 있음
특징
- new 키워드로 인스턴스를 만든 후 사용
- 보통 객체 내부의 데이터를 다룰 때 사용됨
예시
public class Person {
String name;
public void sayHello() {
System.out.println("Hello, my name is " + name);
}
}
// 사용
Person p = new Person();
p.name = "Dain";
p.sayHello(); // 출력: Hello, my name is Dain
✅ 2. 클래스 메서드 (Class Method)
정의
- 객체 생성 없이 호출 가능한 메서드
- static 키워드로 정의됨
특징
- 클래스 이름으로 직접 호출 가능
- 객체의 상태와 무관하게 동작함
- 보통 공통 기능, 유틸리티 기능 등에 사용됨
예시
public class MathUtil {
public static int add(int a, int b) {
return a + b;
}
}
// 사용
int result = MathUtil.add(3, 5); // 객체 없이 호출 가능
5. [Java] 한 번만 등장한 문자 (문자열) - sb.toString();
https://school.programmers.co.kr/learn/courses/30/lessons/120896
틀린 코드
import java.util.*;
class Solution {
public String solution(String s) {
int[] cnt = new int[26];
for(char c : s.toCharArray()) {
cnt[c - 'a']++;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 26; i++) {
if (cnt[i] == 1) sb.append((char)i+'a');
}
return sb.toString();
}
}
✅ sb.append((char)i + 'a');
- 이 int를 char 타입으로 형변환하려는 의도지만, 실제로는 그냥 int로 연산된다.
- 예를 들어, i = 0일 때 char는 연산 시 int로 자동 변환되므로 → 0 + 97
(char)i + 'a' // => 정수 + 정수 → int로 연산됨
→ i + 'a' 전체를 char로 캐스팅해야 문자로 제대로 변환된다.
sb.append((char)(i + 'a'));
개선한 코드
import java.util.*;
class Solution {
public String solution(String s) {
int[] cnt = new int[26];
for(char c : s.toCharArray()) {
cnt[c - 'a']++;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 26; i++) {
if (cnt[i] == 1) sb.append((char)(i + 'a'));
}
return sb.toString();
}
}
10. [Java] 숫자 찾기 - String.indexOf(), String.valueOf()
https://school.programmers.co.kr/learn/courses/30/lessons/120904
틀린 코드
class Solution {
public int solution(int num, int k) {
String numToString = Integer.toString(num);
char[] arr = numToString.toCharArray();
char kToChar = (char) k;
int idx = -1;
for(int i = 0; i < arr.length; i++ ) {
if (arr[i] == kToChar) {
return i+1;
}
}
return idx;
}
}
✅ char kToChar = (char) (k + '0');
- 틀린 부분: char kToChar = (char) k;
- int 타입을 char 타입으로 변환하는 방법이 잘못됨
- → int 3을 (char)로 바꾸면 '3'이 아니라 아스키 문자 'ETX' 같은 이상한 문자가 됨
- → char kToChar = (char)(k + '0'); 또는 Character.forDigit(k, 10); 로 고쳐야 함
개선한 코드
class Solution {
public int solution(int num, int k) {
String numToString = Integer.toString(num);
char[] arr = numToString.toCharArray();
char kToChar = (char) (k + '0');
int idx = -1;
for(int i = 0; i < arr.length; i++ ) {
if (arr[i] == kToChar) {
return i+1;
}
}
return idx;
}
}
더 간단한 방법 (String API 활용)
public int solution(int num, int k) {
String s = String.valueOf(num);
int idx = s.indexOf(String.valueOf(k));
return idx == -1 ? -1 : idx + 1;
}
✅ String.indexOf()
문자열 내에서 특정 문자나 문자열이 처음 등장하는 위치의 인덱스를 알려주는 매우 유용한 메서드이다.
📌 기본 사용법
String s = "29183";
int idx = s.indexOf("1"); // 결과: 2
- 문자열 "1"이 "29183"에서 0-based index 2에 처음 등장
- 못 찾으면 -1을 반환
📌 자바 공식 문법
int indexOf(int ch) // 문자 또는 문자 코드 (ex: 'a', 97)
int indexOf(String str) // 문자열
✅ 삼항연산자
자바의 삼항 연산자(ternary operator)는 if-else를 한 줄로 간단하게 쓸 수 있게 해주는 조건 연산자이다.
📌 기본 사용법
조건식 ? 참일 때 값 : 거짓일 때 값;
- 조건식이 true이면 ? 다음의 값을 반환
- false이면 : 다음의 값을 반환
📌 예제
int age = 20;
String result = (age >= 18) ? "성인" : "미성년자";
System.out.println(result); // 출력: 성인