변수와 상수 모두 하나의 값을 저장하기위한 메모리 공간의 이름
을 의미하고 있다.
변수는 값을 재 할당할 수 있지만, 상수
는 한번 초기화하면 값을 재 할당할 수 없다.
상수는
변수 타입
앞에final
키워드를 이용해서 사용하며, 변수 타입에 final 키워드가 기술되었을 시, 값을 재할당 할 수 없는 "상수" 가 된다.
상수
는 값이 없을 수 없으므로 반드시 선언과 동시에 초기화
해야한다.
int age = 29; // 변수
age = 30; // 메모리 안에 값의 재할당이 가능하다.
final int AGE = 29; // 상수
AGE = 30; // X, 상수는 메모리 안에 값을 재할당 할 수 없다.
리터럴
이란 값 자체
를 의미한다.int score = 100; // 100 은 리터럴
final int MAX = 200; // 200 은 리터럴
String str = "abs" // "abs" 는 리터럴
public class VarEx3 {
public static void main(String[] args) {
int score = 100;
System.out.println(score); // 100
score = 200;
System.out.println(score); // 200
final int SCORE = 300;
System.out.println(SCORE); // 300
//SCORE = 400; Cannot assign a value to final variable 'SCORE'
int local;
//로컬변수는 반드시 초기화 해야한다!
//System.out.println(local);
//Variable 'local' might not have been initialized
}
}
값(리터럴)에 의미있는 이름을 지어주기 위함
이다.유지보수성을 높이기 위함
이다.final int WIDTH = 20;
final int HEIGHT = 10;
// 앞으로 어떠한 곳에 상수가 쓰이던지 상수 값만 바꾸면 모든 식도 수정 된다.
// 식에서 상수의 이름을 보고 값이 어떤 역할을 하는지 알 수 있다.
int triangleArea = (WIDTH * HEIGHT) / 2;
기본 정수형은 int
, 기본 실수형은 double
이다.
0x
0
0b
_(언더바) 구분자
사용이 가능해졌다.long l = 100_000_000_000L; // 크기가 큰 정수형 리터럴 _ (언더바)로 구분할 수 있다.
double
이 된다.float f = 3.14; // X 생략 불가능
변수의 타입과 리터럴의 타입은 일치해야한다.
💫 더 작은 타입이 더 큰 타입으로 자동 변환 되는 것 ⇒
프로모션
💫 더 큰 타입이 더 작은 타입으로 강제 변환 되는 것 ⇒
캐스팅
int i = 'A';
long l = 123;
double d = 3.14f;
System.out.printf("Result > i:%d, l:%d, d: %e",i,l,d);
//Result > i:65, l:123, d: 3.140000e+00
// 타입 자동 변환
값
]이 변수 타입의 허용범위를 벗어나거나, 리터럴의 "타입"
이 변수 타입보다 크다면 컴파일 에러가 발생한다.int i = 0x123456789;
// X , 리터럴의 타입은 인트이지만 int 타입의 범위를 넘어가는 수이기 때문에 대입 불가
float f = 3.14;
// X , 리터럴의 타입은 double(8byte) 이며 변수의 타입은 float(4byte) 이므로 대입 불가
단, int 타입의 리터럴이 변수가 저장할 수 있는 타입의 범위에 속해야만한다.
boolean power = true;
System.out.println(power); // true
System.out.println(!power); // false
//byte b = 128; 리터럴의 범위가 byte 타입의 범위를 넘어섰음
int oct = 010; //8진수, 8
int hex = 0x10; //16진수, 16
System.out.println(oct);
System.out.println(hex);
long l = 1000_000_000; // int -> long 프로모션
long l1 = 10_000_000_000L; //
float f = 3.14f;
double d = 3.14f; // float -> double 프로모션
'[작은 따음표]로 "하나의 문자"를 감싸는 것
은 문자 리터럴이다."[큰 따옴표]로 "문자"를 감싸는 것
은 문자열 리터럴이다.String
타입이며, 참조타입이다.char ch = 'J'; // Character, 문자 리터럴
String str = "Java"; //String, 문자열 리터럴
문자열은 빈 문자열("")을 허용하지만, 문자는 빈 문자를 허용하지 않는다('')
String emptyStr = "";
String oneChar = "A";
char ch = ''; // X -> 문자형 리터럴은 반드시 하나의 문자를 가져야한다.
문자열 리터럴
이다.+
연산은 접합 연산
으로 취급하며, 피연산자 중 문자열이 아닌 쪽을 String 타입으로 바꿔서
접합연산한다.불변성
을 가지고 있어서, 한 번 생성되면 값을 바꾸지 못한다
.새로운 String 객체를 생성하는 것이다.
String 의 불변성은 메모리 상에서는 큰 낭비가 생긴다.
Java 에서는 Heap 영역에String Constant Pool
을 생성하여 객체를 저장해둔다.
문자열로 생성
한 String 객체는 String Constant Pool에 기록
된다.동일한 문자열로 생성
한 String 타입 참조변수는 String Constant Pool 에 있던 같은 객체를 참조
하게 된다.new 연산자로 String 객체를 생성
할 경우, Heap 영역에 따로 String 객체가 생성된다.new 연산자로 생성한 String 은 각자 다른 메모리 주소 값을 가지게 된다.
String str = new String("");
System.out.println(str.hashCode());
str = new String("String");
String str1 = new String("String");
System.out.println(System.identityHashCode(str) + " / "
+ System.identityHashCode(str1));
String str2 = "String";
String str3 = "String";
System.out.println(System.identityHashCode(str2) + " / "
+ System.identityHashCode(str3));
/*
692404036 / 1554874502
1846274136 / 1846274136
*/
String str = new String("");
System.out.println(str.hashCode());
str = new String("String");
String str1 = new String("String");
System.out.println(System.identityHashCode(str) + " / "
+ System.identityHashCode(str1));
String str2 = "String";
String str3 = "String";
System.out.println(System.identityHashCode(str2) + " / "
+ System.identityHashCode(str3));
System.out.println(System.identityHashCode(str2+"?"));
//String 접합 연산은 새로운 객체를 리턴한다.
//
692404036 / 1554874502
1846274136 / 1846274136
1639705018
여기서 접합 연산된 String 객체와 같은 문자열을 가진 String 객체를 문자열로 생성한다면
접합 연산으로 생겨난 문자열 객체와 같은 문자열을 가진 String 객체를 생성해도, String Constant Pool 에는 저장되지 않는다.
즉, 접합 연산으로 생겨난 문자열 객체는 String Constant Pool 에 저장되지 않는다.
String str = new String("");
System.out.println(str.hashCode());
str = new String("String");
String str1 = new String("String");
System.out.println(System.identityHashCode(str) + " / " + System.identityHashCode(str1));
String str2 = "String";
String str3 = "String";
System.out.println(System.identityHashCode(str2) + " / "+ System.identityHashCode(str3));
String strPlus = str2+"?";
System.out.println(System.identityHashCode(strPlus));
//String 접합 연산은 새로운 객체를 리턴한다.
String str4 = "String?";
String str5 = "String?";
System.out.println(System.identityHashCode(str4));
System.out.println(System.identityHashCode(str5));
/*
692404036 / 1554874502
1846274136 / 1846274136
1639705018 <<< 접합 연산된 String 객체의 주소 값
1627674070 << 문자열로 생성했던 String 객체의 주소 값만 같음.
1627674070
*/
public class VarEx4 {
public static void main(String[] args) {
char ch = 'A';
System.out.println(ch);
int i = 'A'; //프로모션, 65
System.out.println(i);
String str = "";// String 타입은 빈 문자열을 허용한다.
String str2 = "ABCD";
String str3 = "123";
String str4 = str2 + str3;
System.out.println(str4);
System.out.println(""+7+7); // 77
System.out.println(7+7+""); // 14
}
}