Day 5. [Java] 변수와 타입, 문자열
Chapter 1. 자바의 개요
💡 학습 목표
- 자바의 4가지 특징을 이해할 수 있다.
- JVM의 기능과 필요성을 이해할 수 있다.
- main 메서드가 무엇인지 이해한다.
자바의 특징
- 운영체제에 독립적
- 특정 CPU에서만 작동하거나 특정 OS에 따라 다르게 작성해야 하는 C, C++ 등의 언어와 다르게 JRE (JVM + 표준 클래스 라이브러리)가 설치되어 있는 모든 운영체제에서 실행이 가능하다.
- 객체 지향 언어(OOP; Object Oriented Programming)
- 함수형 프로그래밍 지원
- 자동 메모리 관리
- 가비지 컬렉터를 실행시켜 자동으로 사용하지 않는 메모리를 수거한다.
JVM(Java Virtual Machine) : 자바 프로그램을 실행시키는 도구
메서드: 어떤 기능을 수행하기 위한 코드들을 묶어놓은 것
반환_타입 메서드_이름(매개변수_타입 매개변수_이름) {
메서드_바디
}
매개변수: 메서드 외부에서 메서드 내부로 전달한 값을 할당받아 저장함으로써, 메서드 내부에서 사용할 수 있게 해준다.
Chapter 2. 변수와 타입
💡 학습 목표
- 타입의 개념을 이해하고 설명할 수 있다.
- 기본 타입과 참조 타입의 차이를 설명할 수 있다.
- 정수 타입, 실수 타입, 논리 타입, 문자 타입을 이해한다.
- 변수, 상수, 리터럴이 무엇인지 설명할 수 있다.
- 자동 타입 변환이 어떤 경우에 발생하는지 설명할 수 있다.
- 수동 타입 변환을 어떤 경우에 사용할 수 있는지, 그리고 어떻게 사용할 수 있는지 설명할 수 있다.
변수(Variable) : 값이 변할 수 있는 데이터를 임시적으로 저장하기 위한 수단
변수 선언 : 값을 저장할 메모리 공간을 확보하고, 해당 메모리 공간을 식별할 수 있는 이름을 붙이는 것
int i;
String str;
값 할당 : 변수에 값을 저장하는 것
int i; // 변수 선언
i = 1; // 값 할당
int num = 2; // 변수 선언과 동시에 초기화
변수를 선언하고 처음으로 값을 할당하는 것을 초기화라고 한다.
초기화 이후 다른 값을 할당하는 것을 재할당이라고 한다.
변수 명명 규칙
일반적으로 카멜 케이스(camelCase)를 사용한다. 카멜 케이스란 두 번째 단어부터 대문자로 시작하는 것을 의미 변수 명으로 영문자, 숫자, _, $를 사용할 수 있으며, 영문자는 대소문자가 구별되어 인식된다. 숫자로 시작하는 변수명은 사용할 수 없다. 자바에서 이미 사용중인 예약어(reserved word)는 변수명으로 사용할 수 없다. (if, this, new, switch, public 등)
int byte; //Error
int class; //Error
String myhome; //Error는 아니지만 camelCase에 맞지 않는 예
String myHome;
String my_Home; //올바른 예
상수(Constant) : 변하지 말아야 할 데이터를 임시적으로 저장하기 위한 수단 (재할당이 금지된 변수)
final 키워드를 사용해 선언하며 관례적으로 대문자에 언더바(_)를 넣어 구분하는 SCREAMING_SNAKE_CASE를 사용한다.
final double CALCULATOR_PI = 3.14;
상수를 사용하는 경우
- 프로그램이 실행되면서 값이 변하면 안되는 경우
- 코드 가독성을 높이고 싶은 경우
- 코드 유지관리를 손쉽게 하고자 하는 경우
타입(Type) : 어떤 값의 유형 및 종류를 의미하며, 타입에 따라 값이 차지하는 메모리 공간의 크기와 값이 저장되는 방식이 결정된다.
기본 타입(primitive type): 데이터의 실제 값이 저장된다
- 정수 타입, 실수 타입, 문자 타입, 논리 타입
참조 타입(reference type): 데이터가 저장된 곳을 나타내는 주소값이 저장된다.
- 8개의 기본 타입을 제외한 나머지
🤍입력
public class Main {
public static void main(String[] args) {
int primitive = 1;
Object reference = new Object();
System.out.println(primitive);
System.out.println(reference);
}
}
🖤출력
1
java.lang.Object@626b2d4a
리터럴(Literal) : 문자가 가리키는 값 그 자체를 의미한다.
정수 타입: 숫자를 나타내는 타입으로 byte, short, int, long 4개의 타입으로 분류된다.
근래에는 메모리 용량이 부족한 경우가 거의 없기 때문에 정수형을 사용할 때 일반적으로 int형을 사용한다.
타입 메모리 표현 범위
byte | 1byte | -128(-2^7) ~ 127(2^7 - 1) |
short | 2byte | -32,768(-2^15) ~ 32,767(2^15 - 1) |
int | 4byte | -2,147,483,648(-2^31) ~ 2,147,483,647(2^31 - 1) |
long | 8byte | -9,223,372,036,854,775,808(-2^63) ~ 9,223,372,036,854,775,807(2^63 - 1) |
long 타입 리터럴의 경우 리터럴 뒤에 접미사 L을 붙여줘야 한다.
정수형의 오버플로우와 언더플로우
오버플로우 : 자료형이 표현할 수 있는 범위 중 최대값 이상의 값을 표현한 경우 발생한다.
언더플로우 : 자료형이 표현할 수 있는 범위 중 최소값 이하의 값을 표현한 경우 발생한다.
실수 타입 : 소수점을 가지는 값을 의미하며 float형과 double형으로 분류된다.
double형 리터럴에는 접미사 d 생략이 가능하지만 float형 리터럴에는 반드시 접미사 f를 붙여줘야 한다.
실수형의 오버플로우와 언더플로우
오버플로우 시 값은 무한대가 되며 언더플로우 시 값은 0이 된다.
논리 타입: boolean형 한 가지이며 true 혹은 false를 값으로 가진다.
문자 타입: char형 한 가지이며 반드시 작은 따옴표(’’)를 사용해야 한다.
문자형 리터럴을 문자형 변수에 할당하면 유니코드 숫자 값이 저장된다.
char letter = 65;
System.out.print(letter); // 출력 결과 : A
타입 변환: boolean을 제외한 기본 타입 7개는 서로 타입을 변환할 수 있다.
자동 타입 변환
- 바이트 크기가 작은 타입에서 큰 타입으로 변환할 때 (예: byte → int)
- 덜 정밀한 타입에서 더 정밀한 타입으로 변환할 때 (예: int → double)
byte(1) -> short(2)/char(2) -> int(4) -> long(8) -> float(4) -> double(8)
수동 타입 변환: 더 큰 데이터 타입을 작은 데이터 타입의 변수에 저장하기 위해서 해야 하며 이를 캐스팅(casting)이라고 한다.
캐스팅 연산자 ()를 사용하며 괄호 안에 변환하고자 하는 타입을 적어주면 된다.
int intValue = 128;
byte byteValue = (byte)intValue;
System.out.println(byteValue); // 오버플로우 발생으로 출력 결과는 -128이다.
Chapter 3. 문자열
💡 학습 목표
- String이 무엇인지 이해한다.
- String을 선언하고 사용하는 법을 이해한다.
- String 메서드들을 이해한다.
- StringTokenizer가 무엇인지 이해한다.
- String Builder, Buffer가 무엇인지 이해한다.
String 타입의 변수 선언과 할당
String name1 = "Cho Hayan"; // 문자열 리터럴을 변수 name1에 할당
String name2 = new String("Moon Jiwon"); //String 클래스의 인스턴스 생성
두 가지 방법 모두 참조 타입의 변수에 할당된다.
위 에제에서 name1과 name2는 실제 문자열의 내용이 아닌 메모리 공간 상의 주소값을 저장하고 있다.
하지만 출력해보면 문자열의 내용이 출력되는데 그 이유는 String 타입의 변수를 참조하면 toString()이 자동으로 호출되기 때문이다.
toString()이 호출되면 String 인스턴스의 내용을 문자열로 변환해준다.
String name1 = "Kim Coding";
String name2 = "Kim Coding";
String name3 = new String("Kim Coding");
String name4 = new String("Kim Coding");
boolean comparison1 = name1 == "Kim Coding"; // true
boolean comparison2 = name1 == name2; // true
boolean comparison3 = name1 == name3; // false
boolean comparison4 = name3 == name4; // false
boolean comparison5 = name1.equals("Kim Coding"); // true
boolean comparison6 = name1.equals(name3); // true
boolean comparison7 = name3.equals(name4); // true
String 클래스의 메서드
- charAt() 메서드 : 해당 문자열의 특정 인덱스에 해당하는 문자를 반환한다.
- compareTo() 메서드 : 해당 문자열을 인수로 전달된 문자열과 사전 편찬 순으로 비교한다. 대소문자를 구분하며 두 문자열이 같다면 0을 반환/ 해당 문자열이 인수로 전달된 문자열보다 작으면 음수를 크면 양수를 반환한다. 대소문자 구분 없이 비교하려면 compareToIgnoreCase() 메서드를 사용
🤍입력
```java
String str = new String("abcd");
System.out.println("문자열 : " + str);
System.out.println(str.compareTo("bcef"));
System.out.println(str.compareTo("abcd") + "\\n");
System.out.println(str.compareTo("Abcd"));
System.out.println(str.compareToIgnoreCase("Abcd"));
System.out.println("compareTo() 메서드 호출 후 문자열 : " + str);
```
🖤출력
```java
문자열 : abcd
-1
0
32
0
compareTo() 메서드 호출 후 문자열 : abcd
```
- concat() 메서드 : 해당 문자열의 뒤에 인수로 전달된 문자열을 추가한 새로운 문자열을 반환한다.
🤍입력
```java
String str = new String("Java");
System.out.println("문자열 : " + str);
System.out.println(str.concat("수업"));
System.out.println("concat() 메서드 호출 후 문자열 : " + str);
```
출력
```java
문자열 : Java
Java수업
concat() 메서드 호출 후 문자열 : Java
```
- indexOf() 메서드 : 해당 문자열에서 특정 문자나 문자열이 처음으로 등장하는 위치의 인덱스를 반환한다. 만약 포함되어 있지 않으면 -1을 반환한다.
🤍입력
```java
String str = new String("Oracle Java");
System.out.println("문자열 : " + str);
System.out.println(str.indexOf('o'));
System.out.println(str.indexOf('a'));
System.out.println(str.indexOf("Java"));
System.out.println("indexOf() 메서드 호출 후 원본 문자열 : " + str);
```
🖤출력
```java
문자열 : Oracle Java
-1
2
7
indexOf() 메서드 호출 후 원본 문자열 : Oracle Java
```
- trim() 메서드 : 해당 문자열의 맨 앞과 맨 뒤에 포함된 모든 공백 문자를 제거한다.
🤍입력
```java
String str = new String(" Java ");
System.out.println("문자열 : " + str);
System.out.println(str + '|');
System.out.println(str.trim() + '|');
System.out.println("trim() 메서드 호출 후 문자열 : " + str);
```
🖤출력
```java
문자열 : Java
Java |
Java|
trim() 메서드 호출 후 문자열 : Java
```
- toLowerCase()와 toUpperCase() 메서드: 모든 문자를 소문자/대문자로 변환시켜 준다.
🖤출력String str = new String("Java"); System.out.println("문자열 : " + str); System.out.println(str.toLowerCase()); System.out.println(str.toUpperCase()); System.out.println("두 메서드 호출 후 문자열 : " + str);
- 문자열 : Java java JAVA 두 메서드 호출 후 문자열 : Java
- 🤍입력
StringTokenizer: 문자열을 우리가 지정한 구분자로 쪼개주는 클래스
🤍입력
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args){
String str = "This is a string example using StringTokenizer";
StringTokenizer tokenizer = new StringTokenizer(str);
System.out.println(str);
System.out.println();
System.out.println("total tokens:"+tokenizer.countTokens());
while(tokenizer.hasMoreTokens()){
System.out.println(tokenizer.nextToken());
}
System.out.println("total tokens:"+tokenizer.countTokens());
}
}
🖤출력
This is a string example using StringTokenizer
total tokens:7
This
is
a
string
example
using
StringTokenizer
total tokens:0
자주 사용하는 메서드
int countTokens(): 남아있는 token의 개수를 반환한다.
boolean hasMoreElements(), boolean hasMoreTokens(): 현재 위치 뒤에 있는 문자열에서 하나 이상의 토큰을 사용할 수 있는 경우 true를 그렇지 않으면 false를 반환한다.
Object nextElement(), String nextToken(): 다음의 토큰을 반환한다.
StringBuilder
🤍입력
public class Main {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("문자열 ").append("연결");
String str = stringBuilder.toString();
System.out.println(stringBuilder);
System.out.println(str);
}
}
🖤출력
문자열 연결
문자열 연결
StringBuffer
String 클래스의 인스터스는 한 번 생성되면 그 값을 읽기만 할 수 있고 변경할 수는 없다.
하지만 StringBuffer 클래스의 인스턴스는 그 값을 변경할 수도 있고, 추가할 수도 있다.
이를 위해 StringBuffer 클래스는 내부적으로 버퍼(buffer)라고 하는 독립적인 공간을 가진다.
append() : 인수로 전달된 값을 문자열로 변환한 후, 해당 문자열의 마지막에 추가한다.
String 클래스의 concat() 메서드와 같은 결과를 반환하지만 내부적인 처리 속도가 훨씬 빠르다.
🤍입력
StringBuffer str = new StringBuffer("Java");
System.out.println("문자열 : " + str);
System.out.println(str.append(" programming"));
System.out.println("append() 메서드 호출 후 문자열 : " + str);
🖤출력
문자열 : Java
Java programming
append() 메서드 호출 후 문자열 : Java programming
capacity() : StringBuffer 인스턴스의 현재 버퍼 크기를 반환
🤍입력
StringBuffer str01 = new StringBuffer();
StringBuffer str02 = new StringBuffer("Java");
System.out.println(str01.capacity());
System.out.println(str02.capacity());
🖤출력
16
20
delete(): 전달된 인덱스의 해당하는 부분 문자열을 해당 문자열에서 제거한다.
deleteCharAt(): 특정 위치의 문자를 해당 문자열에서 제거한다.
🤍입력
StringBuffer str = new StringBuffer("Java Oracle");
System.out.println("문자열 : " + str);
System.out.println(str.delete(4, 8));
System.out.println(str.deleteCharAt(1));
System.out.println("deleteCharAt() 메소드 호출 후 문자열 : " + str);
🖤출력
문자열 : Java Oracle
Javacle
Jvacle
deleteCharAt() 메소드 호출 후 문자열 : Jvacle
insert(): 인수로 전달된 값을 문자열로 변환한 후 해당 문자열의 지정된 인덱스 위치에 추가한다.
이 때 전달된 인덱스가 해당 문자열의 길이와 같으면 append() 메서드와 같은 결과를 반환한다.
🤍입력
StringBuffer str = new StringBuffer("Java Programming!!");
System.out.println("문자열 : " + str);
System.out.println(str.insert(4, "Script"));
System.out.println("insert() 메서드 호출 후 문자열 : " + str);