이 포스팅은 C++이나 C언어에 대해 이해하고 있다는 가정 하에 자바를 간단하게 설명하고 있습니다. C++과의 차이점(C++에는 없지만 자바에는 있는 기능)을 위주로 설명하고 있는 점을 양해 바랍니다. 또한 이 글은 wicidocs의 "Do IT 점프 투 자바"의 내용을 참고하였습니다. 중간 중간에 이해가 안 되시는 분들은 원문을 참조하시기 바랍니다.
자바에서 자료형은 원시(primitive)자료형과 참조자료형으로 구분되는데, new 키워드로 생성할 수 있는 값을 참조자료형이라 하고, 생성할 수 없는 값을 원시자료형이라 한다. 우리가 흔히 아는 int, long, double, float, boolean, char이 원시자료형이고 이외에는 모두 참조자료형이라 생각하면 된다. 원시자료형은 항상 리터럴(literal)로만 값을 set할 수 있다. 리터럴 방식이란 객체 생성 없이 변수에 값을 할당하는 표기법이다. 말이 생소할 뿐 이미 알고 있는 내용이다.
다른 자료형들은 이미 잘 알고 있을 테니, 문자열에 대해서만 살펴보기로 하자. 자바에서 문자열을 나타내는 자료형은 String이다. String은 참조자료형임에도 리터럴 표기법을 적용할 수 있는 유일한 자료형이다. 하지만, 문자열을 표현할 때에는 되도록 리터럴 표기를 사용할 것을 권장한다. 이는 가독성 향상과 컴파일 최적화를 위해서이다.
① equals
② indexOf
③ contains
④ charAt
⑤ replaceAll
⑥ substring
⑦ toUpperCase
⑧ split
문자열 포매팅이란 문자열 안의 특정 값을 바꿔주기 위해 사용하는 기법이다. C에서의 printf와 비슷하다고 생각하면 된다. 예를 들면, "현재 온도는 18도입니다."라는 문장을 시간이 지나 "현재 온도는 20도입니다"라고 출력할 때, 문장 전체를 바꾸는 대신 숫자만 바꿔주면 된다. 사용법은 printf와 유사한데, 이는 System.out.printf()와 System.out.print(String.format())이 동일한 역할을 수행하기 때문이다. 일반적으로 전자의 방법을 선호하나, 조금은 낯설 수 있는 후자의 방법을 소개하기로 한다.
① 숫자 대입(%d)
② 문자열 대입(%s)
③ 여러 개의 값을 동시에 대입
문자열 포맷코드에 익숙하지 않다면 아래의 표를 참고하라.
참고로 %라는 문자를 출력하고 싶다면 %%를 써야 한다. %만 쓰는 경우는 에러가 발생한다.
StringBuffer는 문자열을 추가하거나 변경할 때 사용하는 자료형이다. 내장 메서드는 아래와 같다.
① append
하지만, 두 가지 방법이 완전히 동일한 것은 아니다. 첫번째 예제에서 StringBuffer 객체는 단 한 번만 생성되는 반면, 두번째 예제에서 String 객체는 무려 4번이나 생성된다. 그 이유는 String 자료형은 한번 값이 할당되면 그 값을 변경할 수 없기(immutable하기) 때문이다. 우리 눈에 값이 변경된 것처럼 보이는 모든 것은 사실 또 다른 String객체를 반환 받은 것뿐이다.
그러나 StringBuffer의 경우 값을 변경할 수 있기(mutable하기) 때문에. 객체를 하나만 만든 것이다.
그렇다고해서 StringBuffer가 무조건 유리하다고 말할 수는 없다. StringBuffer자료형은 기본적으로 String자료형에 비해 무겁게 동작한다. 즉, 메모리 사용량도 많고 속도도 느리다. 따라서 문자열을 변경하는 일이 잦은 경우에는 StringBuffer를 사용하고, 문자열 변경이 거의 없는 경우에는 String을 사용하는 것이 효율적이다.
참고로, StringBuffer와 유사한 StringBuilder라는 자료형도 있다. 사용법도 내장메서드도 모두 동일하다. 단, StringBuffer는 멀티 쓰레드 환경에서 안전하고, StringBuilder는 성능이 우수하기에 동기화를 고려할 필요가 없다면, StringBuilder가 유리하다.
② insert
③ substring
String자료형과 공통으로 제공하는 메서드로 사용법은 동일하다.
결과 값으로 Hell이 출력된다.
List자료형에는 List인터페이스를 구현한 ArrayList, Vector, LinkedList가 있다. 자바에서는 배열보다 리스트를 더욱 자주 사용하는데, 그 이유는 리스트가 배열보다 편리한 기능을 많이 가지고 있기 때문이다. 리스트는 크기가 유동적이기 때문에 동적으로 자료형의 개수가 변하는 상황에 대처할 수 있다. List자료형 중 가장 간단한 형태인 ArrayList에 대해 알아보자.
① add
박찬호 선수가 3번의 투구를 138, 129, 142의 속력으로 던졌다고 하자. 투구 구속을 기록하는 리스트는 아래와 같다.
add함수는 insert의 기능을 수행할 수 있도록 오버로딩 되어있다. 따라서 입력인자를 두 개 주면, 해당 인덱스에 원하는 값을 넣을 수 있다.
위의 예제에서는 제네릭스를 사용하지 않고 있지만, 어떤 객체를 포함하고 있는지 명확하게 표현하는 것을 권장한다. 제네릭스는 C++에서의 템플릿과 유사하다. 제네릭스를 사용하여 위의 코드를 변경하면 다음과 같다.
자료형을 명시하지 않아도 잘 동작하는 데 굳이 명시해야 할 이유에 대해 묻는다면, 실행시간의 차이라고 답할 수 있다.
ArrayList에 제네릭스를 적용하지 않으면 리스트 안의 모든 객체를 Object자료형(모든 객체의 공통부모 클래스)으로 인식한다. ArrayList에 값을 넣을 때에는 문제가 안 되지만, 값을 가져올 때에는 항상 Object자료형을 String자료형으로 형변환(casting) 해야 한다.
심지어 ArrayList안에 모든 자료형이 다 들어갈 수 있기 때문에 잘못된 형변환으로 인한 오류가 발생할 가능성도 있다. 제네릭스를 사용한 코드는 아래와 같다.
여기서 get은 특정 인덱스의 값을 얻어오는 메서드이다. 이제 컴파일러도 pitches에는 String밖에 추가될 수 없음을 알기 때문에 형변환을 거치지 않는다. 따라서 불필요한 형변환과 런타임 에러를 방지할 수 있다.
물론, 제네릭스를 사용하면 다양한 자료형을 넣을 수 없다는 단점도 있겠지만, 다양한 자료형을 혼합해서 리스트를 만드는 일 자체가 별로 없으므로 걱정하지 않아도 된다.
② get
③ size
④ remove
① add함수로 ArrayList만들기
② 기존 배열을 이용해 ArrayList만들기
③ String자료형 여러 개를 전달하여 ArrayList만들기
위 예제에서 "138", "129", "142"로 구성된 ArrayList를 만들어보았다. 각 ArrayList의 원소 중간에 콤마를 삽입하여 138,129,142로 출력하고 싶을 때(위 코드의 실행결과는 [138, 129, 142]로 나온다) String.join을 사용할 수 있다.
String.join("구분자", 리스트객체)는 리스트의 각 원소 사이에 구분자를 삽입하여 하나의 문자열로 만든다. 참고로 join은 String클래스의 메서드이므로 ArrayList뿐 아니라 문자열 배열에도 사용할 수 있다.
String.join("구분자", 리스트객체)는 리스트의 각 원소 사이에 구분자를 삽입하여 하나의 문자열로 만든다. 참고로 join은 String클래스의 메서드이므로 ArrayList뿐 아니라 문자열 배열에도 사용할 수 있다.
리스트를 정렬하기 위해선 List클래스의 sort메서드를 활용해야 한다. sort메서드의 파라미터는 오름차순(Comparator.naturalOrder()) 또는 내림차순(Comparator.reverseOrder())이다.