Java 기초 다지기 1

변현섭·2023년 6월 8일
0

Spring 잡학사전

목록 보기
1/10
post-thumbnail

들어가기에 앞서..

이 포스팅은 C++이나 C언어에 대해 이해하고 있다는 가정 하에 자바를 간단하게 설명하고 있습니다. C++과의 차이점(C++에는 없지만 자바에는 있는 기능)을 위주로 설명하고 있는 점을 양해 바랍니다. 또한 이 글은 wicidocs의 "Do IT 점프 투 자바"의 내용을 참고하였습니다. 중간 중간에 이해가 안 되시는 분들은 원문을 참조하시기 바랍니다.

Ⅰ. 자료형

1. 원시자료형 – 문자열

1) 원시자료형과 참조자료형

자바에서 자료형은 원시(primitive)자료형과 참조자료형으로 구분되는데, new 키워드로 생성할 수 있는 값을 참조자료형이라 하고, 생성할 수 없는 값을 원시자료형이라 한다. 우리가 흔히 아는 int, long, double, float, boolean, char이 원시자료형이고 이외에는 모두 참조자료형이라 생각하면 된다. 원시자료형은 항상 리터럴(literal)로만 값을 set할 수 있다. 리터럴 방식이란 객체 생성 없이 변수에 값을 할당하는 표기법이다. 말이 생소할 뿐 이미 알고 있는 내용이다.

다른 자료형들은 이미 잘 알고 있을 테니, 문자열에 대해서만 살펴보기로 하자. 자바에서 문자열을 나타내는 자료형은 String이다. String은 참조자료형임에도 리터럴 표기법을 적용할 수 있는 유일한 자료형이다. 하지만, 문자열을 표현할 때에는 되도록 리터럴 표기를 사용할 것을 권장한다. 이는 가독성 향상과 컴파일 최적화를 위해서이다.

2) String 내장 메서드

① equals

  • 두 개의 문자열이 동일한지 비교하여 결과 값을 반환한다.
  • 문자열을 비교할 때에는 == 연산자 대신 equals를 사용할 것을 권장한다. 그 이유는 ==은 동일한 객체인지를 판별하는 연산자인데 반해, 문자열의 비교는 보통 서로 다른 두 객체의 문자열이 같은지 알아보기 위해 사용되기 때문이다. 아래와 같은 상황이 그 예이다. a와 b객체가 같은지 여부는 별로 관심이 없다. 그저 같은 문자열을 가지고 있는지에 관심이 있을 뿐이다.

② indexOf

  • 문자열에서 특정 문자열이 시작되는 인덱스를 반환한다. 아래의 예를 보자.
  • 다만, 배열의 인덱스는 0부터 시작하므로 human readable로 출력하고 싶다면 결과 값에 1을 더해주어야 할 것이다.

③ contains

  • 문자열에서 특정 문자열이 포함되어 있는지 여부를 반환한다.

④ charAt

  • 문자열에서 해당 인덱스의 문자를 반환한다.

⑤ replaceAll

  • 문자열 중 특정 문자열을 다른 문자열로 바꾼다. replace를 대신 써도 거의 무방하다.

⑥ substring

  • 문자열 중 특정 부분을 뽑아낸다. 마지막 인덱스는 포함되지 않는다는 것에 주의해야 한다.

⑦ toUpperCase

  • 문자열을 모두 대문자로 변경한다. 함께 알아 둘 메서드로 toLowerCase도 있는데, 이 메서드는 문자열을 모두 소문자로 변경할 때 사용한다.

⑧ split

  • 문자열을 특정 구분자로 나누어 문자열 배열로 반환하는 메서드이다. C에서의 strtok와 유사하다.

3) 문자열 Formatting

문자열 포매팅이란 문자열 안의 특정 값을 바꿔주기 위해 사용하는 기법이다. C에서의 printf와 비슷하다고 생각하면 된다. 예를 들면, "현재 온도는 18도입니다."라는 문장을 시간이 지나 "현재 온도는 20도입니다"라고 출력할 때, 문장 전체를 바꾸는 대신 숫자만 바꿔주면 된다. 사용법은 printf와 유사한데, 이는 System.out.printf()와 System.out.print(String.format())이 동일한 역할을 수행하기 때문이다. 일반적으로 전자의 방법을 선호하나, 조금은 낯설 수 있는 후자의 방법을 소개하기로 한다.

① 숫자 대입(%d)

② 문자열 대입(%s)

③ 여러 개의 값을 동시에 대입

문자열 포맷코드에 익숙하지 않다면 아래의 표를 참고하라.

참고로 %라는 문자를 출력하고 싶다면 %%를 써야 한다. %만 쓰는 경우는 에러가 발생한다.

2. StringBuffer

StringBuffer는 문자열을 추가하거나 변경할 때 사용하는 자료형이다. 내장 메서드는 아래와 같다.

① append

  • 문자열을 추가하기 위해 사용된다. vector의 push_back()을 생각하면 된다.
  • toString을 통해 StringBuffer 자료형을 String 자료형으로 바꿀 수 있다. 물론 굳이 바꾸지 않아도 출력하는 데에는 무리가 없다. 즉, 위 예제에서 println(sb)를 해도 동일한 결과를 얻을 수 있다. 당연한 이야기이겠지만, String자료형은 append함수를 지원하지 않는다. 대신 + 연산자를 이용하여 보다 간편하게 문자열을 이어 붙일 수 있다.

  • 하지만, 두 가지 방법이 완전히 동일한 것은 아니다. 첫번째 예제에서 StringBuffer 객체는 단 한 번만 생성되는 반면, 두번째 예제에서 String 객체는 무려 4번이나 생성된다. 그 이유는 String 자료형은 한번 값이 할당되면 그 값을 변경할 수 없기(immutable하기) 때문이다. 우리 눈에 값이 변경된 것처럼 보이는 모든 것은 사실 또 다른 String객체를 반환 받은 것뿐이다.

  • 그러나 StringBuffer의 경우 값을 변경할 수 있기(mutable하기) 때문에. 객체를 하나만 만든 것이다.

  • 그렇다고해서 StringBuffer가 무조건 유리하다고 말할 수는 없다. StringBuffer자료형은 기본적으로 String자료형에 비해 무겁게 동작한다. 즉, 메모리 사용량도 많고 속도도 느리다. 따라서 문자열을 변경하는 일이 잦은 경우에는 StringBuffer를 사용하고, 문자열 변경이 거의 없는 경우에는 String을 사용하는 것이 효율적이다.

  • 참고로, StringBuffer와 유사한 StringBuilder라는 자료형도 있다. 사용법도 내장메서드도 모두 동일하다. 단, StringBuffer는 멀티 쓰레드 환경에서 안전하고, StringBuilder는 성능이 우수하기에 동기화를 고려할 필요가 없다면, StringBuilder가 유리하다.

② insert

  • 특정 인덱스에 원하는 문자열을 삽입한다.
  • 결과 값으로 hello jump to java가 출력된다.

③ substring

  • String자료형과 공통으로 제공하는 메서드로 사용법은 동일하다.

  • 결과 값으로 Hell이 출력된다.

3. 리스트

List자료형에는 List인터페이스를 구현한 ArrayList, Vector, LinkedList가 있다. 자바에서는 배열보다 리스트를 더욱 자주 사용하는데, 그 이유는 리스트가 배열보다 편리한 기능을 많이 가지고 있기 때문이다. 리스트는 크기가 유동적이기 때문에 동적으로 자료형의 개수가 변하는 상황에 대처할 수 있다. List자료형 중 가장 간단한 형태인 ArrayList에 대해 알아보자.

1) 내장 메서드

① add

  • 박찬호 선수가 3번의 투구를 138, 129, 142의 속력으로 던졌다고 하자. 투구 구속을 기록하는 리스트는 아래와 같다.

    add함수는 insert의 기능을 수행할 수 있도록 오버로딩 되어있다. 따라서 입력인자를 두 개 주면, 해당 인덱스에 원하는 값을 넣을 수 있다.

  • 위의 예제에서는 제네릭스를 사용하지 않고 있지만, 어떤 객체를 포함하고 있는지 명확하게 표현하는 것을 권장한다. 제네릭스는 C++에서의 템플릿과 유사하다. 제네릭스를 사용하여 위의 코드를 변경하면 다음과 같다.

  • 자료형을 명시하지 않아도 잘 동작하는 데 굳이 명시해야 할 이유에 대해 묻는다면, 실행시간의 차이라고 답할 수 있다.

  • ArrayList에 제네릭스를 적용하지 않으면 리스트 안의 모든 객체를 Object자료형(모든 객체의 공통부모 클래스)으로 인식한다. ArrayList에 값을 넣을 때에는 문제가 안 되지만, 값을 가져올 때에는 항상 Object자료형을 String자료형으로 형변환(casting) 해야 한다.

  • 심지어 ArrayList안에 모든 자료형이 다 들어갈 수 있기 때문에 잘못된 형변환으로 인한 오류가 발생할 가능성도 있다. 제네릭스를 사용한 코드는 아래와 같다.

  • 여기서 get은 특정 인덱스의 값을 얻어오는 메서드이다. 이제 컴파일러도 pitches에는 String밖에 추가될 수 없음을 알기 때문에 형변환을 거치지 않는다. 따라서 불필요한 형변환과 런타임 에러를 방지할 수 있다.

  • 물론, 제네릭스를 사용하면 다양한 자료형을 넣을 수 없다는 단점도 있겠지만, 다양한 자료형을 혼합해서 리스트를 만드는 일 자체가 별로 없으므로 걱정하지 않아도 된다.

② get

  • 박찬호 선수의 2번째 투구 속력을 출력하고 싶다면 아래와 같이 하면 된다.

③ size

  • size함수는 C++에서와 완전히 동일하다. 최종 인덱스 + 1을 반환한다.

④ remove

  • remove함수도 오버로딩 된 함수로 객체를 입력 받거나 인덱스를 입력 받을 수 있다.
  • remove(객체)의 경우 객체에 해당하는 항목을 삭제하고, 삭제에 성공하면 true, 실패하면 false를 반환한다.
  • 반면 remove(인덱스)의 경우 해당 인덱스의 항목을 삭제하고 삭제된 항목을 반환한다.

2) 다양한 방법으로 ArrayList만들기

① add함수로 ArrayList만들기

② 기존 배열을 이용해 ArrayList만들기

  • Arrays클래스의 asList메서드를 이용하면 기존 배열을 토대로 ArrayList를 만들 수 있다.

③ String자료형 여러 개를 전달하여 ArrayList만들기

  • 위의 방법과 크게 다르지 않다. 다만 data배열이 필요하지 않다.

3) 원소 사이에 구분자 삽입하기(String.join)

위 예제에서 "138", "129", "142"로 구성된 ArrayList를 만들어보았다. 각 ArrayList의 원소 중간에 콤마를 삽입하여 138,129,142로 출력하고 싶을 때(위 코드의 실행결과는 [138, 129, 142]로 나온다) String.join을 사용할 수 있다.

String.join("구분자", 리스트객체)는 리스트의 각 원소 사이에 구분자를 삽입하여 하나의 문자열로 만든다. 참고로 join은 String클래스의 메서드이므로 ArrayList뿐 아니라 문자열 배열에도 사용할 수 있다.

String.join("구분자", 리스트객체)는 리스트의 각 원소 사이에 구분자를 삽입하여 하나의 문자열로 만든다. 참고로 join은 String클래스의 메서드이므로 ArrayList뿐 아니라 문자열 배열에도 사용할 수 있다.

4) 리스트 정렬하기

리스트를 정렬하기 위해선 List클래스의 sort메서드를 활용해야 한다. sort메서드의 파라미터는 오름차순(Comparator.naturalOrder()) 또는 내림차순(Comparator.reverseOrder())이다.

profile
Java Spring, Android Kotlin, Node.js, ML/DL 개발을 공부하는 인하대학교 정보통신공학과 학생입니다.

0개의 댓글