자바의 데이터 타입은 크게 기본 타입primitive과 참조 타입reference으로 분류된다.
기본 타입: 정수(
byte,char,short,int,long), 실수(float,double), 논리
참조 타입: 배열, 열거, 클래스, 인터페이스
둘의 차이점은 저장되는 값이다.
// 기본 타입 변수
int age = 25;
double price = 100.5;
// 참조 타입 변수
String name = "신용권";
String hobby = "독서";

java명령어로 JVM이 구동되면 JVM은 운영체제에서 할당받은 메모리 영역을 다음과 같이 구분해서 사용한다.


==, !=연산자는 변수의 값이 동일한지 조사한다.==, !=연산자는 동일한 객체를 참조하는지 조사한다.참조 타입 변수는
null값을 가질 수 있다.(아직 번지를 저장하고 있지 않음)
null로 초기화 된 참조 변수는 스택 영역에 생성된다.
참조 타입 변수가 null인지 검사: ==, !=연산자 사용
null인 상태에서 객체의 데이터나 메소드를 사용하려 할 때 발생null을 대입하기도 한다.
null을 대입 -> 어떤 변수에서도 객체를 참조하지 않음 -> 해당 객체는 쓰레기가 됨 -> Garbage Collector를 실행시켜 자동으로 제거함
String hobby = "travel";
hobby = null; // "travel"객체는 쓰레기가 됨
String cat1 = "lui";
String cat2 = cat1;
cat1 = null; // "lui"객체는 cat2에서 참조하고 있으므로 쓰레기가 되지 않음
문자열은 참조 타입이다.
선언
문자열은 String 타입을 사용하므로 String 타입의 변수를 먼저 선언해야 한다.
초기화
1. 큰 따옴표(")로 감싼 문자열 리터럴을 사용해 초기화한다.
2. new 연산자로 새로운 문자열 객체를 생성해 초기화한다.
자바는 문자열 리터럴을 내부적으로 String 클래스의 객체로 처리한다.
String name1; // 문자열 선언
name1 = "문자열"; // 문자열 초기화
String name2 = "문자열"; // 문자열 선언과 초기화
String name3 = new String("문자열"); // new 연산자를 사용해 초기화
name1 변수가 가리키는 "문자열" 리터럴은 내부적으로 new String("문자열")를 호출해서 생성한 객체이다. 그러나 내용이 같은 문자열 리터럴이라면 더 이상 새로운 String 객체를 생성하지 않고 기존 리터럴을 공유한다. 따라서 name1과 name2는 동일한 문자열 리터럴을 가리킨다.
name3는 new 연산자로 생성한 객체를 사용해 초기화한 변수이므로 name1, name2과 다른 객체를 가리킨다.
== 또는 != 연산자는 두 문자열의 내용이 아닌 동일한 객체인지를 검사한다.
두 문자열의 내용을 비교하기 위해서는 String 클래스에서 제공하는 문자열 비교 메서드를 사용해야 한다.
name1 == name2 // true
name2 == name3 // false
name1 != name3 // true
String s1 = "Hi, Java";
String s2 = "hi, java";
// 문자열을 사전 순으로 비교 -> 정숫값(int) 반환
s1.compareTo(s2); // -32
// 대소문자 무시하고 문자열을 사전 순으로 비교 -> 정숫값(int) 반환
s1.compareToIgnoreCase(s2); // 0
// 문자열s2와 현재 문자열(s1)을 비교 -> true/false(boolean) 반환
s1.equals(s2); // false
// 대소문자 무시하고 문자열s2와 현재 문자열(s1)을 비교 -> true/false(boolean) 반환
s1.equalsIgnoreCase(s2); // true
▼ String 클래스에서 제공하는 유용한 메서드
String s1 = "Apple ";
String s2 = "Banana";
s1.charAt(1); // index 1 문자를 반환 -> p
s1.concat(s2); // s1 뒤에 s2 연결 -> Apple Banana
s1.contains("a"); // 문자열 "a"를 포함하는지 조사 -> false
s1.endsWith("e"); // 끝나는 문자열이 "e"인지 조사 -> false
s1.indexOf("b"); // 문자열 "b"가 나타난 위치를 반환 -> 없으면 -1
s1.repeat(2); // 2번 반복한 문자열을 반환 -> Apple Apple
s1.replace("Apple", "JAVA"); // 특정 문자열을 다른 문자열로 대체
s1.startsWith("a"); // 시작하는 문자열이 "a"인지 조사(대소문자구분) -> false
s1.substring(3); // index 3 부터 시작하는 문자열의 일부를 반환 -> le
s1.substring(2, 5); // index 2 부터 (5-1)까지 문자열을 반환 -> ple
s1.toLowerCase(); // 모두 소문자로 변환 -> apple
s1.toUpperCase(); // 모두 대문자로 변환 -> APPLE
s1.trim(); // 앞뒤에 있는 공백 모두 제거한 후 반환 -> Apple
s1.isBlank(); // 길이가 0 혹은 공백 있으면 true 반환 -> false
s1.isEmpty(); // 길이가 0이면 true 반환 -> false
s1.length; // s1의 길이를 반환 -> 6
▼ 문자열 분리
split()메소드를 사용한다.split()메소드는 배열(array)을 반환한다.String board = "번호, 제목, 내용, 글쓴이"; // 구분자 == ","
String[] arr = board.split(",");
// {"번호", "제목", "내용", "글쓴이"}
▼ String 클래스에서 제공하는 유용한 "정적" 메서드
String term = String.format("%d - %d %s", 24, 1, "학기"); // 24 - 1 학기
String animals = String.join(", ", "cats", "dogs", "sudal", "panda");
// cats, dogs, sudal, panda
String pi = String.valueOf(3.14); // (문자열)3.14

배열 변수는 참조 변수이다.
배열도 객체이므로 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 주소를 저장한다.
참조할 배열이 없다면 배열 변수도null로 초기화할 수 있다.
{}로 감싼 값의 목록을 변수에 대입할 수 없다.// 선언
int[] intArray;
// 선언 후 값 목록을 대입할 때 -> 'new 타입[]'을 앞에 붙임
String[] names = null;
names = new String[] {"kim", "Ryu", "Han"};
// 값 목록으로 생성
String[] season = {"Spring", "Summer", "Fall", "Winter"};
// new 연산자로 배열 생성
// 값의 목록은 없지만 향후 값들을 저장할 목적으로 배열을 미리 생성할 수 있다.
int[] scores = new int[10];
// new 연산자로 생성한 배열은 배열 변수가 선언된 후에도 대입 가능하다.
int[] scores = null;
scores = new int[10];
메소드의 매개변수가 배열 타입일 경우도 마찬가지
void printItem(int[] scores) { ... } // 메소드 선언 printItem( {95, 82, 67} ); // 컴파일 에러 printItem( new int[] {95, 82, 67} ); // 올바른 메소드 호출
new연산자로 배열을 처음 생성하면, 배열 항목은 기본값으로 초기화된다.
정수 배열은0, 실수 배열은0.0, 논리 배열은false, 참조 배열은null
intArray.length = 10; // 컴파일 에러 발생 !ArrayIndexOutOfBoundsException 발생1차원 배열을 서로 연결한 것

위 그림에서 값1, 값3, 값6을 읽는 법
// 항목에 접근하는 방법: 변수[1차원인덱스][2차원인덱스] ... [N차원인덱스]
값1: 변수[0][0][0]
값3: 변수[0][1][0]
값6: 변수[1][0][1]
[]를 차원의 수만큼 붙이고, 값 목록도 차원의 수만큼 중괄호{}를 중첩시킨다.예제: 1반과 2반의 점수 저장
int[][] scores = {
{ 90, 80, 89 },
{ 76, 88 }
}
scores.lengthscores[0].length, scores[1].length int[][] scores = new int[2][3];
2차원 배열의 길이는 모두 3이고, 항목들은 0으로 초기화된다.
String[][] names = new String[2][3];
2차원 배열의 길이는 모두 3이고, 항목들은 null로 초기화된다.
2차원 배열의 길이를 다르게 주려면?
int[][] scores = new int[2][];
scores[0] = new int[3];
scores[1] = new int[2];
기본 타입 배열은 각 항목에 값을 직접 저장한다.
참조 타입(클래스, 인터페이스) 배열은 각 항목에 객체의 번지를 저장한다.
String[] languages = new String[3];
languages[0] = "Java";
languages[1] = "Java";
languages[2] = new String("Java");

System.out.println(languages[0] == languages[1]); // true
System.out.println(languages[0] == languages[2]); // false
System.out.println(languages[0].equals(languages[2])); // true
배열은 한 번 생성하면 길이를 변경할 수 없다.
더 많은 저장 공간이 필요하다면 더 큰 길이의 배열을 새로 만들고 이전 배열로부터 항목들을 복사해야 한다.
방법 1. for문 사용
int[] oldArray = { 1, 2, 3 };
int[] newArray = new int[5];
// 배열 항목 복사
for (i=0; i<oldArray.length; i++) {
newArray[i] = oldArray[i];
}
// oldArray { 1, 2, 3, 0, 0 }
방법2. System의 arraycopy() 메소드 이용
System.arraycopy(oldArr, 0, newArr, 0, oldArr.length);
// (원본배열, 원본배열복사시작인덱스, 새배열, 새배열붙여넣기시작인덱스,복사항목수)
int[] scores = { 95, 71, 84, 93, 87 };
int sum = 0;
// enhanced for
for (int score : scores) {
sum += score;
}
System.out.println("점수 총합: " + sum);
한정된 값을 갖는 타입
.java)을 생성하고 한정된 값을 코드로 정의해야 한다._로 연결public enum week {
// 열거 상수 목록
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
Week today = Week.SUNDAY;
Week birthday = null;
today == Week.SUNDAY; // true