A. 변수 Variable
프로그램에서 필요한 데이터를 저장하는 메모리 공간 프로그램에서 쓰이는 값들을 저장할 수 있다.
- 변수를 사용하기 위해서는 다음과 같은 과정이 필요
- 변수 선언 : 변수의 데이터 타입과 이름을 선언타입은 자바에서 약속된 키워드들이 있고, 그 예약어들을 이용해서 변수를 선언해주어야 한다.
- 타입과 변수명은 항상 위 순서를 따라야 한다.
- [데이터 타입] [변수명]; int age; // 정수를 저장하는 변수 age 선언
- 변수 초기화 : 변수에 값을 처음으로 저장하는 것을 의미한다.println은 null 값을 인자로 받을 수 없다.맨 처음 변수에 값을 저장하는 것을 초기화라고 한다.위와 같이 age 변수 내에 값을 저장하고 나면, 에러가 발생하지 않는다.
- 값을 저장한다는 것은 할당한다고도 표현한다.
- package com.itwill.variable01; public class VariableMain01 { public static void main(String[] args) { int age; age = 27; // !!!here System.out.println(age); } }
- 그래서 위 프린트 코드는 에러가 나고, 이를 해결하기 위해 변수 age에 값을 저장해야 한다.
- package com.itwill.variable01; public class VariableMain01 { public static void main(String[] args) { int age; System.out.println(age); // error!! } }
- 변수 선언과 초기화는 한 문장으로 작성할 수 있다.
- int x = 100;
- 🍯Tip다음에서 클래스 명 (VariableMain01, String, System)은 파란색, 변수명은 노란색, 예약어는 주황색으로 표현되어 있다.</aside>
- <aside> 💡 IDE에서는 예약어와 변수 등을 색으로 구분 지어 표시한다.
A-1. 변수명 작성 규칙
변수이름을 작성할 때의 규칙은 필수적인 것도 있고 관례적인 것도 있다.
- 변수명은 알파벳, 숫자, 특수기호( 중 _, $)만 사용 가능하다. 필수규칙
- 변수명은 대 / 소문자를 구분한다. 필수규칙
- age와 Age는 다른 변수이다.
- 변수 이름은 숫자로 시작할 수 없다. 필수규칙
- age01이나 age02 같이 숫자가 뒤에 오는 것은 괜찮.
- 하지만 1age나 2age는 불가능하다.
- 변수 이름으로 자바의 키워드는 사용할 수 없다. 필수규칙
- 변수명으로 int나 protected 등의 자바 예약어는 사용이 불가능하다.
- 변수 이름은 변수의 역할에 어울리는 “의미 있는” 단어를 사용해서 만드는 것을 권장. 관례규칙
- 2 단어 이상을 붙여 변수명으로 만들 때 소문자로 시작하는 camelCase 사용하는 것을 권장
- ex) age, name, userId, userPassword …
Java나 C언어에서는 camelCase를 많이 사용하는데 python 에서는 snake_case로 많이 표기한다.
A-2. 변수 사용 시 주의할 점
- 같은 이름으로 2번 이상 변수를 선언할 수 없음.
- 같은 타입이든 다른 타입이든 상관 없음
- 선언된 변수에 재할당하는 것은 상관 없음
- ex ) int x = 1; x = 2;
A-3. 지역변수 멤변수
지역 변수
- 메서드 안에서 선언하는 변수
- 사용 변수
- 지역변수는 선언된 위치에서부터 변수가 포함된 블록 ({… …})안에서만 사용 가능!
- 블록이 끝나면 메모리에서 삭제됨
B. 자바의 기본 데이터 타입
기본 데이터 타입, 즉 기본 자료형은 primitive data type이라고 한다.
해당 자료형은 변수에 값을 저장한다.
기본자료형에 속하는 타입들은 다음과 같다.
- 정수 타입
- byte : 1 byte
- short : 2 byte
- int : 4 byte
- long : 8 byte
- char
- 실수 타입
- float : 4 byte
- double : 8 byte
- 논리 타입
- boolean
- 색 표시한 자료형들이 자바의 기본 타입이다.
- 정수는 int, 실수는 double이 기본이다.
- char는 문자 하나를 저장하는 자료형이다.
- 실제로는 숫자로 저장되어 있으며 각각의 문자를 표현하는 숫자를 나타낸 UNICODE가 있다.
- 자바에서는 다른 데이터 타입의 값을 아예 할당할 수 없다.
왜 자바에서 데이터 타입을 여러 개 만들었을까?
→ 메모리 크기 때문에!
- 메모리 크기가 커지면 커질수록 더 넓은 범위의 수를 표현할 수 있다.
B-1. [숫자]정수편
정수의 기본 타입은 int!
1) byte
- byte 타입의 정수는 -128~127의 범위 내 정수만 저장할 수 있다.
2) short
- short 타입의 정수는 -32768 ~ 32767의 범위 내 정수만 저장할 수 있다.
⁉️ short 도 short(변수) + short(변수)일 경우 에러 발생
byte aa = 111;
byte bb = 123;
short cc = aa + bb;
- byte 변수 값 + byte 변수는 int로 변환됨
- 다음은 두 개의 바이트 변수를 연산했을 때 어느 자료형에 속하는 지를 검증해본 예시
- (1) 의 경우 출력값은 true, (2)의 경우 출력값은 false가 나옴.
- byte + byte가 연산을 거치면서 int가 된다는 사실이 검증됨.
- 이러한 이유 때문에 short나 byte보다 int 를 사용하는 것을 권장
- byte aa = 111; byte bb = 123; System.out.println(Integer.class.isInstance(aa + bb)); // (1) System.out.println(Byte.class.isInstance(aa + bb)); // (2)
- 다음은 두 개의 바이트 변수를 연산했을 때 어느 자료형에 속하는 지를 검증해본 예시
3) int
- int의 범위를 넘어간 수는 에러를 반환한다.
- 범위 : (-2_147_483_648 ~ 2_147_483_647)
4) long
- 범위 : (-9_223_372_036_854_775_808 ~ 9_223_372_036_854_775_807)
- 근데 왜 long에도 안 들어갈까?
- 자바는 기본적으로 정수를 생성할 때 Int형으로 만든다. (literal, 즉 상수)
- 오른쪽에 위치한 값이 int 형의 메모리 공간인 4바이트를 초과하기 때문에 자바에서 에러를 반환한다.
- 이를 해결하기 위해 리터럴의 오른쪽에 L이나 l을 붙인다면 자바가 이를 인식하여 Long 타입의 정수를 만든다. 숫자 상수(literal)가 int 범위를 넘을 때는 숫자 뒤에 L을 붙여줘야 함
- long d = 10_000_000_000L; long e = 10_000_000_000l;
- 더 작은 메모리 공간의 데이터 타입의 상수를 큰 메모리 공간의 데이터 타입 변수에 할당할 수 있으나 그 반대의 상황(메모리 크기 기준)은 불가능하다.
- 🍯Tip</aside>
- <aside> 💡 숫자는 천의 자리마다 _ (언더스코어로) 나눠질 수 있다. 100_000_000 와 같이 표현
B-2. [숫자]실수편
자바의 실수 기본 타입은 double!
실수 저장 방식
$(+-) m * 10^n$
- 부호 / 가수(m) / 지수(n) 를 저장하는 것
- 이러한 저장 방식 때문에 필연적으로 오류가 발생할 수밖에 없음
가수 m은 0 ≤ m < 1 범위의 실수
- $3.14 = 0.314 * 10^1$
- $123.456 = 0.123456 * 10^3$
1) Float
- double보다 더 작은 메모리 공간을 가지고 있는 데이터 타입.
- 기본적으로 실수 리터럴은 double로 생성되기 때문에 이를 해결하기 위해 long과 마찬가지로 리터럴에 float이라는 명시를 해주어야 함.
- double x = 1.0; float y = 1.0f; float z = 1.0F; // float 타입 정수 상수를 만듬.
1) Double
- 실수의 기본 타입
B-3. Character
- 문자 1개의 유니코드(unicode)값(정수)을 저장하는 타입
- 자바는 문자열(String)은 큰따옴표(”), 문자(Character)는 작은 따옴표(’)를 사용한다.
char ch1 = 'a';
Char는 숫자를 저장한다.
package com.itwill.variable04;
public class VariableMain04 {
public static void main(String[] args) {
// 자바 기본 데이터 타입 : 정수편
char ch1 = 'a';
char ch2 = 'b';
System.out.println(ch1); // (1)
System.out.println((int) ch1); // (2)
System.out.println(ch1 + ch2); // (3)
}
}
- (1) : 문자 ‘a’ 출력
- (2) : 문자 ‘a’를 캐스팅(형변환)하여 unicode인 97, 즉 정수로 형 변환되어 출력됨
- (3) :
- 뭐라고 찾아야 할지 몰라서 우선 링크 삽입
- https://cheerant.tistory.com/43
- 인코딩 : unicode, UTF-8, EUC-KR 등 각 문자를 컴퓨터 언어에 대응하도록 결정 방식
- 메모리에 숫자로 저장하고, 만약 출력할 경우 해당 변수가 어떤 데이터 타입인지 찾아본 이후에 문자 ‘a’를 매핑하여 이용함.
- 정수 리터럴(상수)인 경우에만 char에 할당하는 것이 가능
- 위의 코드는 에러 발생
- why? 정수 리터럴이 아니라 변수에 할당된 값을 사용하는 것이기 때문
- 생각 : short나 byte, char에 범위에 맞는 정수 리터럴을 할당했을 때는 가능했음. 그러나 ch1+1 처럼 변수에 할당된 값을 이용했을 때는 ch1+1 자체가 int
- short 도 short(변수) + short(변수)일 경우 에러 발생
- 다음의 경우에도 에러 발생
- short s1 = 10; short s2 = 10; short s3 = s1 + s2;
- 변수 또는 변수가 포함된 연산식인 경우에는 작은 타입에 저장할 수 없다.
- 실제 프로그램이 실행되기 전까지는 이 코드의 오류가 없음을 검증할 수 없기 때문
- 이런 경우, 강제 캐스팅을 통해 에러를 발생하지 않게 할 수 있음.
- short c = (short)(a+b);
- 만약 강제 캐스팅을 했는데, 숫자 범위를 넘어가는 수가 할당될 경우 오버플로우 발생.
- short a = 32767; short b = 33; short c = (short)(a+b); // -32736 출력
- 위의 코드는 에러 발생
- char ch4 = ch1 + 1;
B-3. Boolean
- 논리 타입.
- true(참) 또는 false(거짓) 만을 저장할 수 있는 변수
- 비교연산자나 논리연산자와 함께 사용
- 비교연산자 : ==, !=, >, >=, <, <=
- 모든 연산자 중 대입 연산자는 가장 순위가 낮은 (마지막에 실행되는) 연산자임으로 (1)의 코드에서 우항에 있는 x == y 의 비교 연산을 우선 실행한 후 대입한다.
- 위의 출력 결과는 false
- 보기 좋게 (1)의 표현 대신 boolean b1 = (x == y); 처럼 우항을 괄호를 묶어주는 것을 강사님은 추천!
- package com.itwill.variable05; public class VariableMain05 { public static void main(String[] args) { int x = 2; int y = 4; boolean b1 = x == y; // (1) System.out.println(b1); // false 출력 } }
- 논리연산자 : &&, ||, !
- 연산자 우선 순위 : 비교 연산자 > 논리연산자 > 대입연산자
- (x > 0) 은 True, (x < 19) 또한 True이므로 결과적으로 b2에는 True가 할당된다.
- &&는 우항 좌항 모두 사실이어야 결과적으로 참이 나오는데 반해 ||는 둘 중 하나만 사실이어도 참이 된다.
- package com.itwill.variable05; public class VariableMain05 { public static void main(String[] args) { int x = 2; int y = 4; boolean b2 = (x > 0) && (x < 19); // (1) System.out.println(b2); } }
- 비교연산자 : ==, !=, >, >=, <, <=
B-4. 데이터 타입 관련 주의할 점
- 변수는 같은 타입의 값만 저장할 수 있다.
- 더 큰 범위의 타입에는 작은 범위의 타입의 값을 저장할 수 있다.
- 작은 범위 타입에 큰 범위의 값을 저장하려고 하면 에러가 난다.
- 🐔예외 : 정수 리터럴(상수)은 범위만 넘지 않으면 byte, short, char에 저장 가능하다.
C. 참조 타입
기본타입을 제외한 배열, 열거, 클래스, 인터페이스 등을 의미한다.
값을 저장하는 기본 타입과는 다르게 생성된 객체의 주솟값을 저장한다.
번지로 객체를 참조한다는 의미에서 참조타입이라고 한다.
- 참조 타입 변수는 null 값을 가져 어떤 객체도 참조하지 않을 수 있다.
- 초기화나 재할당 시 null을 참조할 수 있다.
String a = null; // (1) String a = "다음 줄에서 null 값으로 대체"; a = null; // (2)
- ⁉️ warning : NullPointerException
- Null 값을 참조하고 있는 참조 타입 변수의 해당 타입의 메서드나 필드에 접근하려고 할 때 발생하는 에러
- Null 객체를 참조하고 있는 변수의 내부 메서드나 필드는 사용할 수 없다.
C-1. 배열
배열은 왜 필요할까?
package com.itwill.array01; public class ArrayMain01 { public static void main(String[] args) { // 배열의 필요성 int score1 = 100; int score2 = 90; // 총점 int total = score1 + score2; // 평균 double mean = (double) total / 2; System.out.println("평균 = " + mean); } }
만약 두 개의 시험이라면 위와 같이 총점과 평균을 구할 수 있을 것.
하지만 만약 과목의 개수가 늘어난다면…? 변경이 있을 때마다 코드를 수정해야 하고, 많은 수의 변수들을 만들고 계산해야 하는 번거로움이 있을 것…
- 배열(Array) : 같은 타입의 데이터 여러개를 하나의 변수 이름으로 저장하기 위한 메모리
- 인덱스(index) : 배열의 데이터를 저장하거나, 저장된 값을 읽어올 때 사용하는 정수.
- 배열에 데이터가 저장된 위치
- 인덱스는 0부터 시작하는 연속된 정수
- 마지막 인덱스는 (배열 원소 개수 - 1)
- 배열의 특징
- 같은 타입의 값만 저장할 수 있다.
- 선언과 동시에 저장할 수 있는 타입이 결정됨
- 한 번 생성된 배열은 길이를 늘리거나 줄일 수 없다.
- 더 긴 새로운 배열을 생성해서 기존 배열의 값을 복사하여야 함
- System.arraycopy() 메소드 사용하거나 for문 이용
- 더 긴 새로운 배열을 생성해서 기존 배열의 값을 복사하여야 함
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
- src : 원본 배열
- srcPos : 원본 배열의 복사 시작할 인덱스
- dest : 값을 옮길 배열
- destPost : 새 배열의 값을 붙여넣을 시작 인덱스
- length : 복사할 개수
- 같은 타입의 값만 저장할 수 있다.
배열 선언 & 초기화 방법
- &타입[] &변수명 = new 타입[원소 개수];
- int[] scores = new int[3];
- &타입[] &변수명 = {1, 3, 5, 7};
- 기본 값을 미리 제공하여 배열을 만들 때 사용되는 문법
- int[] scores = {1, 3, 5, 7};
- 배열 선언 시에는 length가 정해지지 않고, 배열이 생성될 때에만 length가 정해짐
- 배열 특정 위치(인덱스)에 값을 저장
- 배열[인덱스] = 값;
scores[0] = 100; scores[1] = 97; scores[2] = 80;
- 만약 배열에 저장된 메모리를 넘어가는 index에 접근하려고 하면 에러가 발생 : java.lang.ArrayIndexOutOfBoundsException
배열 사용 시 주의할 점
- 배열 변수 이미 선언한 후, 중괄호를 사용한 배열 생성이 허용되지 않음.
- 위의 경우, new 연산자를 사용해서 값 목록을 지정해주는 방식으로 배열을 생성하여 할당할 수 있음.
- int[] scores; scores = new int[] {7, 4, 8, 7, 6, 5, 3, 10, 2, 9};
- int[] scores; scores = {7, 4, 8, 7, 6, 5, 3, 10, 2, 9};
- 만약 메소드의 매개값으로 배열을 생성하여 넣어주고 싶을 때, 반드시 new 연산자를 사용하여야 함.
- int sum = add (new int[] {7, 4, 8, 7, 6, 5, 3, 10, 2, 9});
- 만약 new 생성자로 배열을 생성할 경우, 각 요소의 초기값은 기본타입 배열의 경우 0이고, 참조 타입 배열인 경우 null임
- 배열의 길이를 알고 싶을 때는 변수명.length를 이용할 수 있다.
- 읽기 전용 필드이기 때문에 값을 변경할 수는 없음
For 반복문을 사용한 배열 원소 출력
for (int i = 0; i < scores.length; i++) {
System.out.println(i + " : " + scores[i]);
}
- 배열이름.length : 배열의 길이(배열의 원소 개수)를 저장하고 있는 속성
향상된 for 구문, for-each 구문
루프 카운터 변수와 증감식을 사용하지 않고, 배열 및 컬렉션 항목의 개수만큼 반복하고 자동적으로 for문을 빠져나감.
- 향상된 for문을 이용할 때 선언한 지역 변수는 배열 내 요소에 대한 접근을 할 수 있으나, 배열 내 요소의 값을 변경할 수는 없다.
- 해당 변수는 배열 내 요소의 값을 저장하고 있는 것이지 주솟값을 참조하고 있는 것이 아니기 때문
- 실행할 값이 있는지 평가
- 해당 변수는 배열에서 꺼낸 값을 임시로 저장하려는 용도로 사
- for ( 타입 변수 : 배열 ) { ... }
- 위에서 예시로 든 scores 배열을 예시로 들면 다음과 같이 사용할 수 있음.
- for (int score : scores) { System.out.println(score); }
names 배열 내의 요소 출력
- 인텍스 이용
- for (int i = 0; i < names.length; i++) { System.out.println(names[i]); }
- 향상된 for문 이용
- for (String name : names) { System.out.println(name); }
예제
- 시험점수를 저장하는 배열에 점수들을 저장하고 (난수),
- 배열의 내용을 출력, 총점 계산 출력, 평균 계산 출력
조건
- 정수 10개를 저장할 수 있는 배열 선언
- for 구문을 이용해서 배열 scores에 정수 (0이상 10이하) 10개 저장
- 배열에 저장된 점수들을 한 줄에 출력
- 배열의 모든 점수들의 합계 출력
- 평균을 계산하고 출력 (double)
- 내가 쓴 코드
- package com.itwill.array02; import java.util.Random; public class ArrayMain02 { public static void main(String[] args) { Random random = new Random(); int[] scores = new int[10]; for (int i = 0; i < 10; i++) { scores[i] = random.nextInt(0, 11); } System.out.println("각 과목의 점수는 공백으로 구분됩니다."); for (int score : scores) { System.out.print(score + " "); } int sum = 0; for (int score : scores) { sum += score; } System.out.println(); System.out.println("과목 총점 : " + sum); double mean = (double) sum / scores.length; System.out.println("과목 평균 : " + mean); } }
[예제]
- 정수 (INT) 10개를 저장할 수 있는 배열을 만들고
- 1이상 4 이하 의 정수들을 임의로 저장하고 그 내용 출력
- 문자열 10개를 저장할 수 있는 배열을 만들고,
- (1)에서 만들 배열의 원소가 1또는 3이면 남성을 저장, 2 또는 4이면 여성을 저
C-2. 다차원 배열
행과 열로 구성된 배열을 2차원 배열이라고 함.
D. 형 변환
- 데이터 타입을 다른 데이터 타입으로 변환하는 것
- 자동 타입변환 (promotion)과 강제 타입 변환(casting)으로 나누어짐
D-1. 자동 타입 변환
- 값의 허용 범위가 작은 타입이 허용범위가 큰 타입으로 저장될 때 발생
- byte 타입보다 int 타입이 허용 범위가 넓기 때문에 자동 타입 변환이 발생
- byte byteValue = 10; int intValue = byteValue;
- 정수 타입이 실수 타입으로 저장될 경우에는 무조건 자동 타입 변환이 일어남
D-2. 강제 타입 변환
E. [메모리 관련 추가]Bit, Byte
- bit : 컴퓨터가 데이터를 저장하는 최소 단위
- 0 또는 1 두가지 값만 가질 수 있음
- 즉, 1비트는 1과 0, 2개의 데이터를 저장할 수 있음.
- 1 Byte = 8 bit;
- 1바이트에는 $2^8 = 256$개의 데이터를 저장할 수 있음.
- 옛날에는 컴퓨터 메모리 자체가 너무 작아서 개발자들이 byte나 short 등의 자료형이 필요했으나, 현재는 기술이 많이 발달해서 int로 사용해도 괜찮음.
'programming > Java [notion 정리본 업로드]' 카테고리의 다른 글
상속 (0) | 2024.04.13 |
---|---|
Class (0) | 2024.04.13 |
연산자 (0) | 2024.04.13 |
조건문과 반복문 (0) | 2024.04.13 |
Java 설치하기 [feat. 17] (0) | 2024.04.13 |