가장 먼저 배운 프로그래밍 언어는 학교 교양 수업으로 들었던 Python이었습니다. 이후에는 C, Java, C++ 등의 순으로 배워 나갔던 기억이 나는데, Python이 압도적이게 편해서 그런지 다른 언어들이 손이 잘 안 가는 게 너무 체감되었습니다.
(데이터 분석이나 딥러닝, 머신러닝 등) 사실 저는 파이토치나 텐서플로를 주로 사용하기 때문에 Python만 잘하면 되겠다! 생각한 것도 있었긴 합니다. 하지만 여러 채용 공고 보면서 느낀건 모델 연구에 있어서 Python도 중요하지만 Java에 대해서도 공부할 필요가 있다는 것입니다.
이미 전공 수업으로 Java를 공부했었지만, 지금은 거의 잘 안 쓰다보니 까먹은 내용도 많기 때문에 다시 공부하고자 스터디에 참여하게 되었습니다. 책은 기존에 구매했었기 때문에 개정판 이전 버전을 보면서 공부하고 있습니다. (내용 변화가 많지 않아서 다행!)
JDK 설치 화면 인증하기
2021년 ~ 2022년 사이에 Java를 처음 배웠으니, 그때 기준으로 설치되어 있고 아마 이후에 몇번 업데이트를 했었던 거 같습니다. 공부하면서 찾아보니까 현재 최신 버전은 무려 23이네요. 업데이트를 조금 더 해볼까 싶습니다.
p.88 02-3 확인 문제 9번에 들어갈 코드를 2가지 이상 작성해보기
long var1 = 2L; float var2 = 1.8f; double var3 = 2.5; String var4 = "3.9"; int result = // 빈칸 채우기 System.out.println(result);
제가 생각했던 답안은 다음과 같습니다. 소수점 부분을 제외하고 2 + 1 + 2 + 3 = 9이기 때문에 타입 변환만 잘 수행해주면 result
에 9를 저장하여 출력할 수 있게 됩니다.
var1 + var2
는 실수형으로 변환되기 때문에 3.8f
가 됩니다. var3
은 정수형으로 변환하여 2로 바꿔주고 3.8f
와 더하면 5.8f
가 됩니다.
그리고 var4
같은 경우에는 문자열이기 때문에 Float.parseFloat(var4)
를 통해 실수형으로 바꿔주고 5.8f
와 더하여 9.7f
가 됩니다. 이후 정수형으로 바꿔줌으로써 result
에 9가 저장될 수 있습니다.
int result = (int) (var1 + var2 + (int) var3 + Float.parseFloat(var4));
다른 풀이도 생각해봤는데 각자 따로 정수형으로 바꿔줘서 더하는게 제가 찾을 수 있는 유일한 다른 풀이인 것 같습니다. 하지만 풀이 1에서 한 것처럼 나중에 정수형으로 바꾸는게 더 편한 것 같습니다.
int result = (int) var1 + (int) var2 + (int) var3 + (int) Float.parseFloat(var4);
모든 운영체제에서 실행 가능
: 윈도우에서 개발된 프로그램을 수정하지 않고 바로 리눅스에서 실행할 수 있다.
객체 지향 프로그래밍
: 객체(부품)을 만들고, 이 객체들을 서로 연결해서 더 큰 프로그램을 완성하는 기법을 적용한다.
메모리 자동 정리
: 메모리를 자동 관리하기 때문에 메모리 관리 부담이 적어진다.
무료 라이브러리 풍부
: 오픈 소스 라이브러리가 풍부하다.
JDK
: JDK는 자바로 프로그램을 개발할 때 사용되는 자바 개발 도구이다. JVM과 컴파일러를 네공하며, Open JDK와 Oracle JDK가 있는데 학습용으로는 둘다 무료로 사용 가능하다.
Java SE AA, B, CC (LTS)
: 알파벳 순서대로 주 버전, 개선 버전, 업데이트 버전, 장기 지원 서비스를 의미한다. Java SE 11. 0. 13 (LTS)면 주 버전은 11이고 개선 버전은 0이니까 아직 주 버전에서 개선 사항이 없다. 그리고 1 ~ 3개월 단위로 버그 수정이 진행되며, 장기 지원 서비스를 지원한다는 것을 알 수 있다.
환경변수
: 환경 변수는 운영체제가 실행하는데 필요한 정보를 제공하는 변수이다. 프로그래밍으로 치면 전역 변수라고 생각하면 된다. 집 주소를 매번 직접 입력하기 보다는 '우리집'으로 저장해두면 지도 앱에서 쉽게 찾을 수 있는 것과 비슷하다.
파일 확장명이 .java
인 텍스트 파일을 생성한다.
1에서 만든 파일을 javac
명령어로 컴파일한다.
컴파일이 완료되면 확장명이 .class
인 바이트 코드 파일이 생성된다.
java
명령어를 실행해서 3에서 만든 파일을 JVM이 기계어 번역 후 실행한다.
프로그램이 실행된다.
자바가 JVM을 사용하는 이유는 바이트 코드 파일을 수정하지 않고 다양한 운영체제에서 사용할 수 있도록 하기 위한 것이다.
개발자가 윈도우 운영체제에서 편하게 프로그램(바이트 코드 파일)을 개발하고, 개발이 완료된 프로그램을 리눅스로 옮겨서 바로 실행할 수 있다.
JVM은 윈도우용, 리눅스용 등으로 나뉘는데 각각 OS에서 실행할 수 있는 기계어로 번역해서 코드를 실행하게 되는 것이다.
클래스 이름은 소스 파일명과 동일해야 한다. 사진 속 클래스 이름은 Hello
이기 때문에 파일 이름도 Hello.java
가 된다.
class
: 클래스는 필드 또는 메소드를 포함하는 블록으로, 메소드는 어떤 일을 처리하는 실행문들을 모아 놓은 블록이다.
public class
: public class
는 공개 클래스라는 뜻이다. 어디서든 접근 가능하기 때문에 다른 패키지나 클래스에서도 해당 클래스를 자유롭게 사용할 수 있다.
public static void main (String[] args)
: public static void main (String[] args)
는 메소드 선언부로서, Java
명령어로 바이트 코드 파일을 실행하면 main()
메소드를 가장 먼저 찾아서 블록 내부를 실행한다. 결국 이 부분이 프로그램 실행의 진입점이 된다. main()
메소드가 없으면 파일이 실행되지 않는다.
로컬 변수
: 로컬 변수
는 블록 내에서 선언된 변수를 로컬 변수라고 한다. 로컬 변수
는 메소드 블록 내부에서만 사용되고 메소드 실행이 끝나면 메모리에서 자동으로 사라진다.사진 속 num
은 main()
메소드 블록 내부의 로컬 변수임을 알 수 있다.
변수 선언 시에는 해당 변수가 어떤 범위에서 사용될 것인지를 생각하고 선언 위치를 결정해야 한다.
예를 들어, 메소드 블록 전체에서 사용하고 싶다고 하면 메소드 블록 첫 머리에 선언한다. 특정 블록 내부에서만 사용하고 싶다면 해당 블록 내에서 선언하는 것이다.
자동 타입 변환
: 자동으로 타입 변환이 발생한다. 값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 저장될 때 발생하게 된다.
기본 타입의 허용 범위 크기 순
: byte < short < int < long < float < double
이기 때문에 작은 허용 범위 타입이 자동으로 큰 허용 범위 타입으로 변환된다.
정수 타입 변수가 산술 연산식에서 피연산자로 사용되면 int
타입보다 작은 byte
, short
타입의 변수는 int
로 자동 타입 변환되어 연산을 수행하게 된다.
물론 모든 변수가 int
로 변환되는 것은 아니며, 두 피연산자 중 허용 범위가 큰 타입으로 변환되어 연산을 수행한다.
강제 타입 변환
: 큰 허용 범위 타입을 작은 허용 범위 타입으로 강제로 나눠서 저장하는 것이다.
문자열을 기본 타입기본 타입(byte
, short
, char
, int
, long
, float
, double
, boolean
)으로 변환하는 경우도 많다. 이 때는 Type.parseType(문자열)
형태로 작성하여 바꿀 수 있다. 예를 들어, 문자열을 int
형으로 바꾸고 싶다면 Integer.parseInt(문자열)
과 같이 작성하면 된다.
하지만 문자열이 숫자가 아닌 알파벳이나 특수 문자, 한글 등을 포함하고 있을 때는 숫자 타입으로 변환하면 숫자 형식 예외가 발생할 수 있다.
반대로 기본 타입(byte, short, char, int, long, float, double, boolean)의 값을 문자열로 변경하는 경우도 있다. 이 때는 String.valueof(기본타입값)
메소드를 이용하면 된다.
System.in.read()
: 시스템이 가지고 있는 입력 장치에서 키코드를 읽어올 수 있다. 키코드를 읽어오는 것은 read()
가 수행한다.
System.out.println()
: 시스템이 가지고 있는 출력 장치로 괄호 안의 내용을 출력하고 행을 바꾼다.
public static void main(String[] args) throws Exception
: System.in.read()
에 대한 예외 처리 코드이다. 예외가 발생했을 때 단순히 모니터에 예외 내용을 출력만 하게 된다.
System.in.read()
는 키코드를 하나만 읽지만 여러 개를 읽고 싶을 때는 Scanner
를 사용하면 된다.
import java.util.Scanner;
를 통해 스캐너를 불러온다.
Scanner scanner = new Scanner(System.in);
을 통해 스캐너 변수를 선언하고 시스템의 입력 장치로부터 읽는 스캐너는 생성한다. 오른쪽에서 왼쪽으로 생성된 스캐너를 변수에 저장하게 된다.
String inputData = scanner.nextLine()
처럼 문자열로 선언해서 스캐너를 통해 읽은 내용을 문자열 형태의 inputData
변수에 저장한다.
equals()
: 문자열이 동일한지 비교할 때 사용하는 메소드이다. 같으면 true
를, 다르면 false
를 반환한다.참고로 스캐너 클래스 이용 시에 leak
관련 문제가 발생할 수 있으니 scanner.close()
를 이용해서 스캐너를 닫아주는 것을 권장한다.
++피연산자
: 다른 연산을 수행하기 전에 피연산자의 값을 1 증가시킨다.
피연산자++
: 다른 연산을 수행한 후에 피연산자의 값을 1 증가시킨다.
피연산자들이 byte
, short
, char
타입인 경우에는 모두 int
타입으로 변환한 다음에 연산을 수행한다.
피연산자들이 모두 정수 타입이고 long
타입이 포함되어 있으면 모두 long
타입으로 변환한 다음에 연산을 수행한다.
피연산자 중 실수 타입(float
, double
)이 있다면 허용 범위가 큰 실수 타입으로 변환한 다음에 연산을 수행한다.
삼항 연산자는 3개의 피연산자를 필요로 하는 연산자이다. ? 앞의 조건식에 따라 콜론 앞 뒤의 피연산자가 선택되는 형태이다.