🥊 이 글은 제대로 파는 자바 - Java 끝.장.내.기 (얄팍한 코딩사전) 강의 내용을 정리한 글입니다.
int age; // 변수 선언
System.out.println(age); // ⚠️ 컴파일 에러 (아직 값이 없으므로 사용할 수 없음)
age = 20; // 초기화
System.out.println(age); // 20 (이제 해당 값을 사용 가능)
char ch1, ch2, ch3; // 선언만
char ch4 = 'A', ch5 = 'B', ch6 = 'C'; // 선언과 초기화 동시에
byte
: 1byteshort
: 2byteint
: 4bytelong
: 8byte
byte _1b_byte = 127; // 1byte
short _2b_short = 32767;
int _4b_int = 2147483647; // 가장 많이 쓰임
long _8b_long = 9223372036854775807L; // 끝에 L 붙여야 함
byte byteNum;
int smallIntNum = 123;
// 명시적(강제) 형변환
byteNum = (byte) smallIntNum; // byteNum: 123
// 강제로 범주 외의 값을 넣을 경우 값 손실
int intNum = 12345;
byteNum = (byte) intNum; // byteNum: 57 (12345 % 128)
float
: 4bytedouble
: 8byte
double
: float
보다 단순히 범위가 넓은 것이 아니라, 보다 정밀하게 표현 가능float flt1 = 3.14f; // float는 뒤에 f 또는 F를 붙여 표현
double dbl1 = 3.14;
// float에는 double을 담을 수 없음
float flt2 = dbl1; // error
// 반대는 가능
double dbl2 = float1;
char
char
: 2byte
// 각 문자는 상응하는 정수를 가짐
char ch1 = 'a'; // ch1: 'a' 97
char ch2 = 'a' + 1; // ch2: 'b' 98
char ch3 = '가'; // ch3: '가' 44032
char ch4 = '가' + 1; // ch6: '각' 44033
int ch1Int = (int) ch1; // ch1Int: 97
// 문자 리터럴, 숫자, 유니코드로 표현 가능
char ch5 = 'A'; // ch5: 'A' 65
char ch6 = '65'; // ch6: 'A' 65
char ch7 = '\u0041'; // ch7: 'A' 65
// 빈 문자 사용 불가, 공백(space)은 가능
char empty = ''; // error
String emptyStr = ""; // emptyStr: "" String은 빈 문자열 가능
char space = ' '; // space: ' ' 32
boolean
boolean
: 1byte
boolean bool1 = true;
boolean bool2 = false;
String
String str1 = "Hello World!"; // 리터럴 방식
String str2 = ""; // 빈 문자열 가능
String str3 = new String("Hello World!"); // 인스턴스 생성 방식
String hl1 = "Hello";
String hl2 = "Hello";
String wld = "World";
// 리터럴끼리는 == 을 사용하여 비교 가능
boolean bool1 = hl1 == hl2; // bool1: true
boolean bool2 = hl1 == wld; // bool2: false
String hl3 = new String("Hello");
String hl4 = new String("Hello");
// 인스턴스와 비교하려면 .equals 메소드를 사용해야 함
// 특별한 경우가 아니면 문자열은 .equals로 비교할 것
boolean bool3 = hl3 == hl4; // bool3: false
boolean bool4 = hl1.equals(hl2); // bool4: true
boolean bool5 = hl1.equals(hl3); // bool5: true
boolean bool6 = hl3.equals(hl4); // bool6: true
boolean bool7 = wld.equals(hl2); // bool7: false
// 같은 곳을 참조하는 인스턴스들
String hl5 = hl4;
boolean bool8 = hl4 == hl5; // bool8: true
boolean bool9 = hl4.equals(hl5); // bool9: true
// 리터럴로 선언했어도 객체 인스턴스로 생성되기 때문에 메소드 사용 가능
String str = "Hello";
boolean bool = str.equals("Hello"); // bool: true
String str1 = "%s의 둘레는 반지름 X &d X %f입니다.";
String circle = "원";
int two = 2;
double PI = 3.14;
// formatted(인스턴스 메소드): 주어진 형식에 따라 문자열 생성 (13+버전에 추가됨)
String str2 = str1.formatted(circle, two, PI); // str2: "원의 둘레는 반지름 X 2 X 3.140000입니다."
// 이전 버전에서의 방식(클래스 메소드)
String str3 = String.format(str1, circle, two, PI); // str3: "원의 둘레는 반지름 X 2 X 3.140000입니다."
// 시스템의 printf 메소드: String.format과 같은 형식으로 출력 (줄바꿈X)
System.out.printf("%s의 둘레는 반지름 X &d X %f입니다.", circle, two, PI); // 원의 둘레는 반지름 X 2 X 3.140000입니다.
Formatter | 자료형 |
---|---|
%b | 불리언 |
%d | 10진수 정수 |
%f | 실수 |
%c | 문자 |
%s | 문자열 |
%n | (포맷 문자열 내 줄바꿈) |
String[] intFormats = {
"%d", // 1. 기본
"%13d", // 2. 13자리 수 확보, 오른쪽 정렬
"%013d", // 3. 빈 자리 수 0으로 채움
"%+13d", // 4. 양수는 앞에 + 붙임
"%,13d", // 5. 쉼표 사용
"%-13d", // 6. 13자리 수 확보, 왼쪽 정렬
"%+,013d" // 7.
};
출력 결과:
String[] fltFormats = {
"%f", // 1. 기본 (소수점 6자리, 0으로 채움)
"%.2f", // 2. 소수점 2자리까지
"%13.2f", // 3. 정수 자리 확보, 소수 자리 제한
"%,f", // 4. 쉼표 사용
"%+013.2f", // 5.
"%-13.2f" // 6.
};
출력 결과:
String[] strFormats = {
"%s", // 1. 기본
"%9s", // 2. 자리 확보
"%.2s", // 3. 2글자만
"%9.2s", // 4.
"%-9s" // 5. 왼쪽 정렬
};
출력 결과:
""
vs null
String emptyStr = "";
String nullStr = null;
// 빈 문자열과 null은 다름
boolean bool1 = emptyStr == nullStr; // bool1: false
// null은 문자열 인스턴스 메소드 사용 불가
// 아래의 코드들은 모두 런타임 에러를 발생시킴 (NullPointerException)
int int1 = nullStr.length();
boolean bool2 = nullStr.equals(emptyStr);
String str1 = nullStr.concat("ABC");
""
: 길이 0. 힙 공간에 자리를 차지null
문자열: 힙에 할당되지 않음. 가리키는 곳이 없음null
String notInitStr;
String nullStr = null;
System.out.println(notInitStr); // 컴파일 에러
System.out.println(nullStr); // null
null
가능Object obj = null;
System sys = null;
// 원시값들도 참조 자료형의 인스턴스로는 null 가능
Integer nullInt1 = null;
Double nullDbl1 = null;
Boolean nullBool1 = null;
Character nullChr1 = null;
// 원시값은 불가
int nullInt2 = null; // 컴파일 에러
char[] yutnori = {'도', '개', '걸', '윷', '모'};
배열을 초기화하지 않고 선언하면
선언과 동시에 초기화
// 선언 동시 초기화
char[] dirArr1 = {'동', '서', '남', '북'}; // 방법1
char[] dirArr2 = new char [] {'동', '서', '남', '북'}; // 방법2
char[] dirArr3;
// 선언만 먼저 한 상태에서는 방법2만 가능
dirArr3 = {'동', '서', '남', '북'}; // 컴파일 에러
dirArr3 = new char [] {'동', '서', '남', '북'};
primitive type
) vs 참조 자료형(reference type
)// 원시 자료형은 값 자체를 복사 - 별개의 값이 됨
boolean initTrue = true; // initTrue: true
boolean initFalse = false; // initFalse: false
initFalse = initTrue; // initFalse: true
initTrue = false; // initTrue: false
// 참조 자료형은 주소값을 복사 - 두 변수가 같은 주소를 가리키게 됨
boolean[] boolArr1 = { true, true, true };
boolean[] boolArr2 = { false, false, false };
boolArr2 = boolArr1;
boolArr1[0] = false; // boolArr1: [false, true, true], boolArr2: [false, true, true]
다중 배열 내 배열의 크기가 다를 수 있는 이유: 배열은 참조형(주소값)이므로
문자열은 객체(참조형)지만 원시형처럼 다뤄짐
String str1 = "코인 함";
String str2 = "관심 없음";
str2 = str1;
str1 = "고점에 익절"; // str1: "고점에 익절", str2: "코인 함"
final int[] NUMBERS = { 1, 2, 3, 4, 5 };
// 다른 배열 할당 불가
NUMBERS = new int[] { 2, 3, 4, 5, 6 }; // 컴파일 에러
// 배열 요소를 바꾸는 것은 가능
NUMBERS[0] = 11; // NUMBERS: [11, 2, 3, 4, 5]
Java 10
에서 도입됨var
연산자로 변수 선언 - 타입을 명시하지 않음 (대입된 값을 통해 컴파일러가 추론)var intNum = 1;
var doubleNum = 3.14;
var charLet = 'A';
var StringWord = "Hello";
// 아래와 같이는 사용 불가 (컴파일러가 타입을 추론할 수 없음)
var notItit; // 초기화 안 됨 - 컴파일 에러
var nullVar = null; // null로 초기화 - 컴파일 에러
// 자료형 변경 불가
intNum = 1.23; // 컴파일 에러
StringWord = 123; // 컴파일 에러
// 배열의 경우 초기화할 때 명시
var chars = new char[] { 'A', 'B', 'C', 'D', 'E' };
var chars2 = { 'A', 'B', 'C', 'D', 'E' }; // 불가