[포스코x코딩온] 풀스택 웹개발자 과정 9기 16주차 회고 | Java 기본 문법

심재운·2023년 10월 20일
post-thumbnail

0. 개요


[포스코x코딩온] 풀스택 웹개발자 과정 9기에서 그동안 HTML, CSS, Node.js, React등을 배우고 드디어 마지막 커리큘럼인 JavaSpring으로 들어섰다.

최근 백엔드 신입 채용 공고를 많이 살펴보는데,

1. Python & Django
2. JavaScript & Node.js
3. Java & Spring

위 3가지 선택지 중

Java & Spring이 정말 압.도.적으로 많았다.
아예 백엔드의 코딩테스트 언어는 Java로 지정한 회사도 꽤 많아서,
마지막 커리큘럼인 JavaSpring을 정말 많이 공부해야겠다고 느꼈다.

그럼 . . .

백엔드의 꽃인 JavaSpring을 지금부터 시작해보겠다!

1. 식별자 원칙


식별자란 우리가 흔히 변수, 함수, 상수, 클래스 등에 붙이는 이름을 말한다.

식별자는

- _(언더바), $(달러)를 제외한 @, #, ! 같은 특수문자 사용 X
- 공백 불가
- 한글 사용도 가능 (권장 X)
- 미리 정의된 키워드(예약어)는 사용 X
- 숫자 사용 가능 (단, 첫 글자로는 X)

위와 같은 규칙이 존재하며, 올바른 예시와 잘못된 예시는 아래와 같다.

- 올바른 예시 -
char ch;
int user_id; // _(언더바) 사용 OK
void $func() {} // $(달러) 사용 OK
class Hello3 {} // 숫자 사용 OK
int 가격; // 한글 사용 가능 OK

- 잘못된 예시 -
int if; // if(예약어) 사용 X
class 3Hello {} // 숫자를 첫 글자로 사용 X
char name! // !(특수문자) 사용 X

① 자바의 예약어

자바에는 매우 많은 예약어가 존재하며 예시는 아래와 같다.

2. 데이터 타입


자바의 데이터 타입은 크게 기본형참조형이 존재한다.

기본형 타입실제 데이터 값을 저장하는 타입으로, 메모리의 스택 영역에 저장한다.

참조형 타입기본형 타입을 제외한 모든 타입을 의미하며 실제 데이터 값은 힙 영역에 저장하고 이를 참조하는 주소를 스택 영역에 저장한다.

또한, 기본형의 초기값은 0이고 참조형의 초기값은 null이다.

스택 영역힙 영역에 대한 자세한 설명은 아래 링크를 확인하길 바란다.

[JAVA! 자바 기본자료형과 참조형 스택과 힙?]

① 기본형 데이터 타입

기본형 타입의 종류는 위와 같으며, 각 타입별 크기와 데이터 범위가 다르다.

여기서 실수형 타입의 경우 실제 값을 저장하는게 아니라 근사값을 저장하므로 금융 계산이나 군사용 프로그램 등 매우 중요한 연산이 필요한 상황에는 적합하지 않다.

약간의 오차가 발생하는 이유는,

floatdouble을 보면 크기가 각각 4Byte, 8Byte인 것을 확인할 수 있는데,

이렇게 되면 순환소수나 소수점 아래가 매우 긴 숫자들은 각 크기의 범위를 벗어나게 된다.

따라서 그 뒤에 소수점 값은 잘리게 되며 이때 약간의 오차가 발생하게 되는 것이다.

	BigDecimal a = new BigDecimal("0.2");
	BigDecimal b = new BigDecimal("0.1");

	BigDecimal sum = a.add(b); // 덧셈
	BigDecimal diff = a.subtract(b); // 뺄셈
	BigDecimal multi = a.multiply(b); // 곱셈
	BigDecimal divi = a.divide(b); // 나눗셈

따라서 정확한 소수점 연산을 위해서는 위와 같이 BigDeciaml 클래스를 이용해야 하며.

아래 영상을 확인해 보면 매우 쉽게 이해할 수 있을 것이다.

[위 수식이 틀린 이유는?]

② 참조형 데이터 타입

// 문자열
String name = "simson";

// 배열
int[] numbers = new int[3];

// 클래스
class Person {
    String name;
    int age;
}
Person person = new Person();

참조형 타입은 종류가 매~우 다양하며, 크게 배열, 열거, 클래스, 인터페이스 범주로 나뉜다.

3. 입력과 출력


입력에는 Scanner 클래스 이외에 BufferedReader도 존재하며, 속도는 BufferedReader가 더 빠르다.

해당 게시글에는 Scanner에 대한 설명만 작성하므로 추가적인 내용은 아래 링크에서 확인하길 바란다.

[BufferedReader와 BufferedWriter의 사용법 (JAVA)]
[[Java/자바] 입력 BufferedReader와 Scanner의 차이]
[BufferedReader / Scanner 의 속도차이]

① 입력

import java.util.Scanner; // Scanner import 필수

Scanner sc = new Scanner(System.in); // Scanner 객체 생성

String name = sc.next(); // 문자열 읽기
int age = sc.nextInt(); // 정수 읽기

Scanner 클래스는 위 처럼 import 후 객체를 생성해서 사용할 수 있다.

// 공백의 의미 : 공백(스페이스바), 탭(\t), 엔터(\n)
next() : 공백 이전까지의 문자열 읽기
nextLine() : \n 이전까지의 문자열 읽기 (한줄읽기)
nextInt() : 공백 이전까지의 정수 읽기
nextDouble() : 공백 이전까지의 실수 읽기
nextBoolean() : 공백 이전까지의 논리값 읽기
close() : Scanner 닫기

주요 메서드로는 위와 같으며, 예시는 아래를 참고하길 바란다.

import java.util.Scanner;
public class Velog {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		System.out.println("이름을 입력하세요");
		String name = sc.next(); // 문자열
		System.out.println("나이를 입력하세요");
		int age = sc.nextInt(); // 정수
		System.out.println("키를 입력하세요");
		double height = sc.nextDouble(); // 실수
	}
}

② 출력

System.out.println("하이"); // 출력 후 마지막에 Enter(\n)
System.out.print("안녕하세요"); // 출력

[출력결과]
하이
안녕하세요

출력은 위와 같이 할 수 있으며

서식지정자를 활용하는 System.out.printf()는 바로 아래에서 설명하겠다.

③ 서식지정자 (형식지정자)

import java.util.Scanner;
public class Velog {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		System.out.println("이름을 입력하세요");
		String name = sc.next(); // 문자열
		System.out.println("나이를 입력하세요");
		int age = sc.nextInt(); // 정수
		System.out.println("키를 입력하세요");
		double height = sc.nextDouble(); // 실수
        
        System.out.printf("이름 : %s\n", name);
        System.out.printf("나이 : %d\n", age);
        System.out.printf("키 : %.1f\n", height);
	}
}

[출력결과]
이름 : naem값
나이 : age값
키 : height값

서식지정자 또는 형식지정자는 출력 시 데이터 타입을 지정하는 것이다.

위 예시와 같이 %s는 문자열, %d는 정수, %f는 실수 등으로 지정할 수 있으며 서식지정자와 변수의 개수를 똑같이 작성해주면 된다.

이외에 서식지정자는 아래와 같다.

4. 연산자


int a = 5;
int b = 2;

System.out.println(a + b); // 덧셈 => 7
System.out.println(a - b); // 뺄셈 => 3
System.out.println(a * b); // 곱셈 => 10
System.out.println(a / b); // 나눗셈(몫) => 2
System.out.println(a % b); // 나눗셈(나머지) => 1

연산자+, -, *, /, % 가 있으며, 위 예시에서 a / b는 원래 2.5이지만 int 자료형이므로 2가 나오게 된다.

2.5가 나오게 하기 위해서는 (double)a / b로 두 숫자 중 하나를 실수형으로 변환해주면 2.5가 나오게 된다.

여기서 주의할 점은 a / b의 연산 결과인 2실수형으로 변환하는 것이다.

a / b는 이미 정수형 숫자의 연산 결과이므로 (double)(a / b)로 작성하면 2.0이 나오게 되므로 괄호를 잘 작성하여 형변환 해줘야 한다.

단순 산술 연산자 이외에도 논리 연산자, 비교 연산자, 시프트 연산자 등 여러 종류가 존재하니 다른 연산자들도 확인하길 바란다.

5. 조건문


① if문

	System.out.print("수를 입력하세요 : ");
	int num = sc.nextInt();

	if (num % 3 == 0) {
		System.out.println("3의 배수 입니다.");
	} else {
		System.out.println("3의 배수가 아닙니다.");
	}

자바에서 if 사용법은 다른 언어들과 똑같으므로, if ~ elseif ~ else if ~ else 모두 사용 가능하다.

다만, 문자열을 비교할 때 주의할 사항이 있는데, String은 위에서 설명했듯이 참조형 데이터 타입이다. String의 실제 데이터는 힙 영역에 존재하고 스택 영역에는 이를 참조하는 메모리의 주소 값이 저장된다.

따라서 == 연산자로는 비교가 불가능하고 변수.equals("문자열") 형태로 값을 비교해야 한다.

	System.out.print("이름을 입력하세요 : ");
	String name = sc.nextLine();

	if (name.equals("simson")) {
		System.out.println("simson님 매우 매우 환영합니다!!!!!");
	} else {
		System.out.printf("%s님 환영합니다.\n", name);
	}

② switch문

	System.out.print("수를 입력하세요 : ");
	int num = sc.nextInt();
    
	switch (num % 3) {
	case 0:
		System.out.println("3의 배수 입니다.");
		break;
	default:
		System.out.println("3의 배수가 아닙니다.");
	}

위 예시 코드는 if문에서 사용한 예제의 switch 버전으로, switch (값)case 값을 일치시켜 각 상황에 맞는 코드를 실행시킬 수 있다.

case 1, case '+', case "남자" 이런식으로 각 데이터 타입에 맞게 잘 작성하도록 주의하길 바란다.

6. 반복문


forwhile은 매우 자주 사용하므로 기본 사용 방법과 활용 예시를 많이 알아두면 좋다!

① for문

for (int i = 0; i < 10; i++) {
	System.out.println(i);
}

for의 기본 문법은 for (초기값; 조건식; 증감) 이다.

위 코드의 for (int i = 0; i < 10; i++)의 의미는 아래와 같다.

초기값 : int i = 0
조건식 : i가 10 보다 작을 때까지 이므로 9까지를 의미
증감식 : i++로 i는 반복문을 수행하며 계속 1씩 증가

따라서 위 예시는 i0부터 9까지 1씩 증가하며 출력되는 코드가 된다.

조건식배열의 크기, 문자열의 길이 등과 같이 작성하여 활용하는 예시가 많으므로 많은 예시를 접해보길 바란다.

① while문

int i = 0;

while (i < 10) {
	System.out.println(i);
    i++;
}

for의 예시와 똑같은 동작을 하는 코드로,

while 밖에 int i = 0을 먼저 선언하고 while문 맨 끝에 i++를 작성하여 임의로 i를 증가시킨 코드이다.

만약 반복문이 언제 끝날지 모르는 경우에는

while (true) {
	// 반복할 동작
    if (조건) {
    	break;
    }
}

이런식으로 while (true)를 작성하여 무한 반복 코드를 작성할 수 있다.

이럴 경우에는 if를 사용해서 while을 탈출할 수 있는 break를 작성해주면 된다.

7. 메서드


public class Main {
	// 반환값이 없는 void
	public static void hello() {
		System.out.println("반환값이 없는 void!!");
	}
    
    // 2개의 숫자를 더해서 반환 (int형 반환)
    public static int calc(int a, int b) {
   		return a + b;
	}
    
    public static void main(String[] args) {
    	hello(); // hello 메서드 동작
        System.out.println(calc(1, 2)); // 3 출력
    }
}

함수란 특정 기능을 수행하는 코드로, 어디에 속하지 않고 단독적으로 호출하여 사용할 수 있다.

메서드함수의 일종으로, 클래스 내부에 속한 함수를 뜻한다. 클래스 내부에 존재하는 멤버 변수들을 이용하는 함수로.

독립적이냐, 클래스 내부에 종속되어 있느냐로 함수메서드를 구분할 수 있다.

① 메서드 오버로딩

메서드 오버로딩은 한 클래스 내에서 "동일한 이름"의 메서드를 여러 개 정의하는 것을 의미한다.

메서드 오버로딩의 조건은

  1. 메서드 이름이 같아야 한다.
  2. 메서드의 매개변수의 타입, 개수, 순서가 달라야 한다.

위 조건을 성립하면 아래와 같이 add라는 이름의 똑같은 메서드를 여러 개 정의할 수 있다.

public class Over {
	// 정수 두개를 더하는 메서드
	public int add(int a, int b) {
		return a + b;
	}
	
	// 실수 두개를 더하는 메서드
	public double add(double a, double b) {
		return a + b;
	}
	
	// 정수 세개를 더하는 메서드
	public int add(int a, int b, int c) {
		return a + b + c;
	}
	
	// 정수, 실수를 더하는 메서드
	public double add(int a, double b) {
		return a + b;
	}
	
	// 실수, 정수를 더하는 메서드
	public double add(double a, int b) {
		return a + b;
	}

	public static void main(String[] args) {
		Over calc = new Over();
		
		System.out.println(calc.add(10, 20)); // 첫번째 add 실행
		System.out.println(calc.add(0.15, 0.3)); // 두번째 add 실행
		System.out.println(calc.add(10, 20, 30)); // 세번째 add 실행
		System.out.println(calc.add(5, 1.5)); // 네번째 add 실행
		System.out.println(calc.add(1.5, 5)); // 다섯번째 add 실행
	}
}

위 5개의 add 메서드는 모두 매개변수 타입이 다르거나, 매개변수 개수가 다르므로 메서드 오버로딩의 조건을 성립한다.

add 메서드를 사용할 때, 매개변수를 입력 후 add에 마우스 커서를 올려보면 어떤 메서드가 실행되는지, 매개변수의 타입과 개수는 몇 개인지 나온다!

이때, 반환 타입은 메서드 오버로딩의 조건과 관계가 없으므로, 반환 타입을 수정하는 실수는 하지 않도록 유의하길 바란다.

오늘 설명한 내용들의 코드는 모두 [깃허브]에서 확인 가능하다!

8. 마무리


오늘은 Java의 정말 기본 of 기본 of 기본 of 기본을 배웠다.

솔직히 아직은 Java를 배웠다! 라고 하기에는 애매하고...

추후 클래스나 오버라이딩, 객체, 상속 등 더욱 깊은 내용까지 배워야
Java를 배웠다! 라고 할 수 있을 것 같다.

하지만, 뭐든 기본이 가장 중요하기 때문에 쉽고 다 아는 내용이라도
자만하지 않고 확실히 짚고 넘어가야 한다고 생각한다.

미래에 백엔드 개발자가 된 모습을 상상하며 더욱 노력해야 겠다.

화이팅이다...!

profile
공부는 비효율적으로 하는 게 가장 효율적이다.

1개의 댓글

comment-user-thumbnail
2024년 4월 11일

안녕하세요, 혹시 해당 수업 어떠셨을까요??!

답글 달기