🦁멋쟁이사자처럼 백엔드 부트캠프 13기 🦁
TIL 회고 - 2일차
🚀2일차에서는 "자바의 기초"를 좀 더 다지고 과 "자바의 문법" 등을 배웠습니다📖
<자바 기초와 문법>
❓main메소드
main메소드가 포함된 클래스는 "프로그램의 시작점"을 의미합니다.
시작점은 한 곳이듯 다른 클래스들이 만들어져도 그 클래스들을 가져다 쓸 main메소드는 프로그램에서
하나만 존재해야합니다.
이 main메소드가 포함된 클래스는 JVM(자바가상머신 Java Virtual Machine)이 사용하는데,
이 JVM은 같은 패키지도 아니고, 자식클래스도 아니기때문에 접근제한자를 public으로 지정해주어야합니다.
<public static void로 선언된 main메소드의 예시>
public class MyInfo {
public static void main(String[] args) {
String name = "홍길동";
String gender = "남";
String email = "Hong@zmail.com";
System.out.println("'"+ name + "'의 성별은 ("
+ gender + ")이며, 이메일은 [" + email + "]입니다.");
}
}
저번 내용을 복습해보자면, 접근제한자는 4가지가 있는데 [public / protected / default / private]이 있습니다.
public : 제한없이 사용 가능
protected : 같은 패키지, 상속받는 자식클래스까지 사용 가능
default : 같은 패키지에 소속된 클래스에서만 사용가능 (같은 패키지에서는 사용 가능)
private : 나만 사용가능 (같은 클래스 내에서만 사용 가능)
❓String[] args의 의미
: 이는 String타입으로 선언된 배열 args를 의미하는데, 처음 프로그램이 main메소드를 실행하게되면
아규먼트인 String타입으로 선언된 배열 args는 메모리에 올라갑니다.
순서를 정리해보면
- main메소드 실행
- Heap메모리에 String배열 "인스턴스"가 만들어짐
- 이 인스턴스를 스택 엔트리에 있는 args 변수가 “참조하게 됨”
메모리는 스택 메모리와 힙 메모리로 나누어지는데
이 중 힙 메모리에는 참조형타입 변수, 스택 메모리에는 기본형타입 변수가 저장됩니다.
String[] args 배열로 살펴보면
"args 변수"는 스택 메모리에 저장되고, 생성된 배열(String[])의 공간(=인스턴스)이 힙 메모리에 저장이 됩니다.
args변수는 힙 메모리에 저장된 배열(String타입의 배열)을 주소값으로 "참조"하게 되는 것입니다.
String[] args 배열은 값을 여러개 받을 수 있는데 argument 데이터를 받아옵니다.
args[0] : 0번째 배열의 값
args[1] : 1번째 배열의 값
args[2] : 2번째 배열의 값
따라서 argsTest클래스를 작성한 후
public class argsTest{
public static void main(String[] args){
System.out.println(args[0]);
System.out.println(args[1]);
System.out.println(args[2]);
}
}
1) 첫번째 방법은 터미널 창에서 javac 명령어와 java 명령어를 통해 args배열에 값을 전달하는 방법입니다.
javac argsTest.java
➡️javac : 리눅스 명령어로 컴파일을 의미
java argsTest Apple Banana Strawberry
➡️java : 리눅스 명령어로 클래스를 실행함을 의미
➡️Apple Banana Strawberry : args에 데이터로 넣어줄 값들을 의미. 여기서는 3개의 값을 args배열에 전달하고 있습니다.
2) 두번째 방법은 IntelliJ IDE에서 Edit Configurations 창을 통해 접근하는 방법입니다.
- IntelliJ창의 위에 있는 클래스이름을 누르고, Edit Configurations창으로 진입합니다.
+버튼을 눌러 Application을 누른 후 Name을 임의로 지정해줍니다.
그 후 박스 부분에 패키지명.클래스이름 (⚠️패키지가 없으면 클래스이름만 적어줘도 자동완성됩니다.)을 입력하고
Program Argument 부분에
Apple Banana Strawberry를 공백을 기준으로 입력한뒤 OK를 눌러 빠져나옵니다.
컴파일을 해보면 잘 출력되는 것을 확인할 수 있습니다.
❓자바의 변수명
public static void main(String[] args) {
int a = 10;
int _1 = 10; // 언더바(_) 사용 가능
int $2 = 10; // 달러 표시 사용 가능
int abc = 10;
int $abc = 10;
int _abc = 10;
int abcdefabcdefabcdefabcdef = 10;
// <불가능한 경우>
// int @abc = 10;
// int while = 10;
// int public = 10;
// int true = 10;
// int a* = 10; (X) : 특수문자 사용불가능
// int class = 10; (X) : 키워드이기때문에 사용불가능
이처럼 특정 문자로는 언더바(_)와 달러표시($)만 변수에 쓰일 수 있고, 나머지 특수문자는 불가능합니다.
static, void, class와 같은 키워드들도 사용이 불가능합니다.
❓자바의 타입
자바의 타입에는 크게 2가지가 있습니다.
기본형 타입 (Primitive Type) 과 참조형 타입이라고도 불리는 레퍼런스 타입 (Reference Type)
<기본형타입>
- 논리형 - boolean
- 문자형 - char
- 정수형 - byte, short, int, long (공간의 크기에 따라 다름 (=그릇의 크기))
각각 1바이트, 2바이트, 4바이트, 8바이트 - 실수형 - float, double
여기서 바이트는 비트가 모여있는 것을 의미합니다. 1바이트는 8비트입니다.
예를 들면 1byte는 00000000 처럼 1비트가 8개 모여있는 형태입니다.
// <기본형 타입>
byte b = 127; // -128~127
byte b1 = 1234; // (X) : 크기 초과
short sh = 10; // -32,768 ~ 32,767
short sh1 = 32768; // (X) : 크기 초과
int i = 10; // -2,147,483,648 ~ 2,147,483,647
int iboom1 = 2147483647;
int iboom2 = 2147483648; // (X) : 크기 1 초과
byte는 1바이트, 즉 8비트가 모여있는 형태로써
00000000 부터 11111111 값까지 가질 수 있습니다.
11111111는 2진수이므로 10진수로 변환하면 숫자 255를 의미하는데
byte는 -128부터 +127까지의 공간에 숫자를 가질 수 있다는 의미입니다.
따라서 위 예제의 b1처럼 1234 숫자를 넣고자 하면 크기 초과로 에러가 발생합니다.
short는 2바이트, 즉 8비트가 2개 모여있는 형태로써
00000000 00000000 부터 11111111 11111111 값까지 가질 수 있습니다.
이를 10진수로 변환하면 숫자 65535를 의미하는데
short는 -32,768 부터 32,767까지의 공간에 숫자를 가질 수 있다는 의미입니다.
여기서도 마찬가지로 최대값 32767보다 1 더 큰 32768을 넣고자하면 에러가 발생합니다.
이처럼 기본형타입의 데이터타입에 따라 저장할 수 있는 값의 범위를 고려하여 변수를 설정해주어야합니다.
❓기본형타입을 객체로 쓸 수 있는 방법
Wrapper 클래스 사용
// 각 기본형타입이 사용가능한 범위를 "객체 Wrapping"를 활용하여 출력하는 예제
public class MinMaxValue {
public static void main(String[] args) {
System.out.println("byte형의 최소값 : " + Byte.MIN_VALUE);
System.out.println("byte형의 최대값 : " + Byte.MAX_VALUE);
System.out.println("-----------------------------------");
System.out.println("short형의 최소값 : " + Short.MIN_VALUE);
System.out.println("short형의 최대값 : " + Short.MAX_VALUE);
System.out.println("-----------------------------------");
System.out.println("int형의 최소값 : " + Integer.MIN_VALUE);
System.out.println("int형의 최대값 : " + Integer.MAX_VALUE);
System.out.println("-----------------------------------");
System.out.println("long형의 최소값 : " + Long.MIN_VALUE);
System.out.println("long형의 최대값 : " + Long.MAX_VALUE);
}
}
Byte.
Short.
Integer.
Long.
처럼 대문자로 시작하여 . (온점)으로써 MIN_VALUE() 메소드와 MAX_VALUE() 메소드에 접근하고 있습니다.
MIN_VALUE()메소드는 이 자료형의 최소값을 반환하는 메소드이고,
MAX_VALUE()메소드는 이 자료형의 최대값을 반환하는 메소드입니다.
<레퍼런스 타입>
String타입은 객체이자, 참조형 타입
이러한 레퍼런스 타입은 값이 바로 담기는 것이 아니라 주소값을 참조하는 변수만 스택에 담깁니다.
이렇게 값이 바로 담길 수 있는 영역을 “스택”이라고 하는데요, 그 외 영역을 “힙”이라고 합니다.
스택에는 레퍼런스 타입이 담기는 주소가 있는 곳이고,
이 주소가 가리키는 실제 인스턴스는 "힙" 메모리에 저장이 되어있습니다.
String타입 변수 str을 선언 후 str. (점)을 하게되면 사용가능한 메소드가 출력되는데,
이는 클래스일 경우, 즉 객체일 경우에 출력이 된다.
자바의 경우 객체지향언어로써 자바의 존재하는 모든 것들은 객체로 존재해야하지만 (ex. 클래스)
기본형 타입은 유일하게 객체가 아닌 경우입니다.
ex. equals() : 같은 문자열인지 비교하는 기능을 하는 메소드
단적인 예시로는 byte, short, int, boolean ... 처럼 소문자로 시작하면 "기본형타입"
String 처럼 대문자로 시작하면 "참조형타입"이라고 참고할 수도 있습니다.
❓논리연산자 (AND, OR, XOR, NOT)
AND연산은 && 을 쓰며, a > 20 && a < 50
"a는 20보다 “크고,” 50보다 작다" 를 의미합니다.
OR연산은 || 을 쓰며, a > 20 || a< 50
"a는 20보다 “크거나” 50보다 작다"를 의미합니다.
AND와 OR연산은 연산자를 &, | 처럼 하나만 써주어도 같은 결과가 나옵니다.
연산자 2개를 사용하는 것이 일반적 : && , ||
💡연산자 1개를 사용하는 경우는 비트값을 연산하는 “비트연산자”
정리)
AND = 제시한 조건을 모두 만족해야 통과
OR = 제시한 조건 중 하나라도 만족하면 통과
<XOR연산자>
^ (윗꺾쇠) exlusive-or 혹은 XOR 라고 말합니다.
2개의 조건식의 “논리 값이 서로 다를 경우” >> 참이 됩니다.
a = 31
a > 10 ^ a < 20
a > 10은 참, a < 20은 거짓이므로,
참과 거짓은 서로 다르므로, (true & false) >> 참이 나오게된다.
<부정연산자 !>
논리형 값을 반대로 부정한다.
true → false
false → true
❓&&, || 연산자와 &, | 연산자의 차이점
int a = 10;
boolean result = a > 20 && a < 50;
AND연산 && 2개를 쓸 경우
1. 첫번째 연산자(a > 20)를 먼저 판단하여
2. AND연산은 두 조건 모두 만족해야 true이기 때문에
3. 첫번째 연산자가 false 이면 뒤의 연산은 생각하지 않고 바로 false를 반환한다.
위 예제의 경우 a = 10이기때문에 첫번째 연산자 (a > 20)에서 false가 발생하여 false반환
int a = 30;
boolean result = a > 20 && a < 50;
OR연산 || 2개를 쓸 경우
1. 첫번째 연산을 먼저 판단한다.
2. OR연산은 두 조건 중 “하나라도 만족”하면 true가 나오기때문에
3. 앞에 있는 조건식이 true이면 뒤의 연산을 실행하지 않는다.
위 예제의 경우 a = 30이기때문에 첫번째 연산자 (a > 30)에서 true가 발생하여 뒤에는 실행을 하지 않는 것이다.
AND연산 & 1개를 쓸 경우에는
첫번째 연산이 false라 할지라도 뒤의 연산을 실행한다.
따라서
int i = 10;
flag = b < 200 && i++ > 5;
와 같은 문구가 있을 경우
&&연산이 2개쓰였으므로 뒤의 i++ 증감연산자 연산을 수행하지 않으므로,
i = 10 값이 그대로 보존된다.
OR연산 & 1개를 쓸 경우에는
첫번째 연산이 true여서 두 조건 중 하나라도 만족을 하지만 뒤의 연산까지 수행하여
i++ (증감연산자)로 인해 i = 11이 된다.
이처럼)
비트연산자는 11111111 00000000 모든 자리를 연산해야하기때문에
따라서 비트연산자는 앞의 조건식의 true, false 상관없이 뒤의 연산까지 모두 수행합니다.
어떠한 경우에는 비트연산자를 꼭 수행해야하는 경우가 있는데
(++a, --a)전위 연산자가 붙어있을때 꼭 수행합니다.
(이 식을 수행안하면 그 식이 바뀌지 않으므로 비트연산자를 사용)
❓논리형 타입(boolean)은 메모리를 얼마나 사용할까?
- 1byte 즉 8bit를 사용한다.
- 사실 1비트로도 참과 거짓은 표현할 수 있다.
- 0 = 거짓, 1 = 참 으로 표현
- 💡하지만 컴퓨터는 자료를 표현하는 “최소단위가 1byte”이기 떄문에 boolean형 타입은 메모리에 1byte를 사용하게된다.
❓자바의 형변환
- 자바 컴파일러는 그릇안에 들어있는 값은 신경쓰지 않고, 그릇의 크기만 비교합니다.
int i = 10;
long iLong1 = i; // 묵시적 형변환 (자동 형변환)
long iLong2 = (long)i; // 명시적 형변환 (강제 형변환)
System.out.println("int i의 값 = " + i);
System.out.println("long타입으로 묵시적 형변환 후 값 = " + iLong1);
System.out.println("long타입으로 명시적 형변환 후 값 = " + iLong2);
i = iLong1;
같은 경우 컴파일러는 iLong1처럼 long타입의 큰 값을, int타입의 작은 그릇에 넣어주는 것을 판단하지 못하기때문에
개발자(사용자)가 직접 처리해주어야합니다.
개발자가 판단했을때 "에러가 안날 것 같고 충분히 옮겨도 될 것 같다!" 라는 판단이 있으면
명시적으로 형변환을 하겠다고 선언하는 것 = "명시적 형변환"
i = (int)iLong1;
(기본형타입) ex. (int) 처럼 기본형타입을 괄호로 감싸주어 명시적으로 형변환을 해줄 수 있습니다.
이를 “명시적 형변환”이라고 합니다.
정리하자면,
작은 그릇 → 큰 그릇 : 컴파일러가 묵시적 형변환
큰 그릇 → 작은 그릇 : 개발자가 컴파일러한테 명시적 형변환할 것임을 표시 (ex. (int))
❓long타입과 float 타입 중에는 어느 타입이 더 큰 메모리 공간을 가질까?
float은 4바이트, long타입은 8바이트로 float형이 더 작습니다.
하지만 큰 long타입에 작은 float타입을 저장하고자 하면 에러가 발생합니다.
큰 그릇에 작은 값을 저장하고자했는데 에러가 발생하는 이유는 float는 실수형 타입이기때문에
정수형 타입인 long타입은 소수점을 보관할 수 없는 것입니다. (소수점이 유실될 수 있음)
따라서 컴파일러는 에러를 발생시킵니다.
// <정수형과 실수형 타입의 형변환>
long l = 10;
float f = 10f;
l = f; // 에러 발생, 컴파일러가 형변환을 해도되는 것인지 물어봄
l = (long)f; // 개발자가 명시적으로 형변환을 함
위 예제의 float타입은 소수점이 없는 단순 10f 값을 가지는데, 소수점이 유실되지 않음에도
컴파일러는 에러를 발생시킵니다. 위에서 말했듯 “실제 값을 비교하는 것이 아니라 그릇의 크기만 비교"하기때문입니다.
따라서 실제 값이 무엇인지는 중요하지 않고, 기본형 타입의 타입만 보고 판단하는 것입니다.
또한 형변환이 가능하기 위해서는 데이터 타입이 같아야합니다.
위와 같은 경우는 실수형, 정수형 모두 “숫자”이기때문에 가능한 것입니다.
- 데이터타입이 다른 경우 (long타입에 boolean형을 담는 것은 불가능)
// <데이터 타입이 다른 경우의 형변환>
long l = 10;
boolean flag = true;
l = (long)flag; // (X)
- 데이터타입이 같은 경우 char는 숫자값을 가지고 있습니다.
문자로 표시되지만 유니코드 상에서 숫자를 가지고 있기 때문입니다.
💡문자 타입은 0~65535까지 저장할 수 있는 정수 타입 - char자체가 코드값으로 되어있어서 숫자로 매핑되는 값을 가지고 있습니다.
따라서 char을 숫자형으로 형변환을 할 수 있습니다.
// <char 문자 타입의 형변환>
char c = 'a';
int i = c;
System.out.println( (char) i ); // a 출력
i++;
System.out.println( (char) i ); // b 출력
유니코드 상에서 +1을 증가하게되면, a에서 b 문자로 넘어가기때문에 b가 출력되는 것 또한 확인할 수 있습니다.
💡유니코드의 97번째 값은 ‘a’이다.
char c2 = (char)97;
System.out.println(c2);
c2는 [ a ] 가 출력
❓삼항연산자
// 삼항연산자 관련 예제
public class TernaryOpExam01 {
public static void main(String[] args) {
// (조건) ? 식1 : 식2
// 조건이 true면 식1 실행, false면 식2 실행
int num = 10;
String result = (num > 0) ? ("[" + num + "]은 양수입니다.") : ("[" + num + "]은 음수입니다.");
System.out.println(result);
// 반환값에 따라 타입 다르게 지정하기
boolean flag = (num % 2 == 0) ? true : false;
String result1 = (num % 2 == 0) ? "짝수" : "홀수";
}
}
❓Switch 문
public class SwitchExam01 {
public static void main(String[] args) {
String fruit = "딸기";
switch(fruit){
case "딸기":
System.out.println("딸기입니다.");
break;
case "사과":
System.out.println("사과입니다.");
break;
default:
System.out.println("딸기나 사과가 아닙니다.");
}
}
}
❓do-while 문
public class RepeatExam02 {
public static void main(String[] args) {
// do-while문 예제
// 조건비교는 나중에
int num = 10;
do { // 탈출조건식이 참일 경우 실행되는 코드 (변수의 증감식)
System.out.println("num은 10이지만, do-while문으로 인하여 한번 실행되는 출력문입니다.");
}while(num > 10); // 탈출조건식
}
}
▶️실습
for문을 "회고팀 리스트업 프로그램"으로 활용한 예제 입니다.
// 1) break문을 적용한 예제
// 오늘 출석한 인원
int students = 35;
int lionClass = 1;
for(int i = 0; i <= students; i++){
if(i != 0 && i % 7 == 0){
// 7명씩 회고팀에 넣습니다.
System.out.println("-->> 이 학생들은 [" + (lionClass++) + "]회고팀 입니다.");
}
if(i == students) break;
System.out.print((i+1) + "\t");
}
기본 for문에 break문을 적용하여, i가 35와 일치할 경우 break문을 걸어주어,
for문의 조건식 i <= students임에도 for문을 빠져나가게 만들었습니다.
// 2) continue문을 적용한 예제
System.out.println("--------팀장 선출 중--------");
// 위의 예제에서 진행하여 나온 회고팀의 수를 teams 변수로 넣음
int teams = lionClass;
// team 리더들의 번호를 담을 배열을 선언 (인덱스이므로 실제크기에서 -1)
int[] teamLeaders = new int[teams-1];
// 배열 인덱스 접근 변수
int k = 0;
for(int i = 1; i <= students; i++){
// 팀장들의 번호인 7의 배수에서는 배열에 담김
if(i % 7 == 0){
teamLeaders[k++] = i;
System.out.println();
continue;
}
// 팀장이 아닌 학생 번호들을 출력
System.out.print(i + "\t");
}
System.out.println("--------회고팀 팀장 리스트--------");
int count = 1;
for(int x : teamLeaders){
System.out.println(x + "번 학생은 [" + (count++) + "]회고팀 팀장입니다.");
}
이전에 만든 회고팀의 수 (lionClass 변수)를 활용하여 배열의 크기를 초기화하고
7번째의 학생마다 회고팀 팀장으로 지정해보았습니다.
가장 밑의 for문은 for-each문을 이용하여 teamLeaders 배열에 있는 요소들을 int x에 하나씩 넣어
System.out.println(x)를 통해 출력하고, count 변수에 후위증감식을 사용하여 각 회고팀에 팀장을 배정하였습니다.
💡 2일차에는 자바의 문법을 조금 더 활용하여 많은 실습을 해보고자 하였습니다!
'Recording > 멋쟁이사자처럼 BE 13기' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_6일차_'상속과 메소드 오버라이딩' (1) | 2024.12.09 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_5일차_'메소드, 필드, static' (3) | 2024.12.06 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_4일차_'객체지향프로그래밍' (1) | 2024.12.05 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_3일차_'배열과 객체' (1) | 2024.12.04 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_1일차_'자바 기초' (0) | 2024.12.02 |