📖 개발 언어의 역사 💬
A 언어 : 첫 개발 언어라는 의미의 A Programming Launguage.
1960년대에 발표되어서 프로그램을 만들기 위한 기초적인 기능 입출력, 문맥 기능만 구현
B 언어 : Bell 사에서 개발한 언어.
1960년대에 개발되어, A언어의 기능에 데이터를 담을 수 있는 타입(숫자형 타입, 문자형 타입)이 생겼다.
데이터를 연산( +, -, *, / )하고, 묶어서 관리하는 메서드(프로그램이 하는 행동을 정의한 것)구현이 가능한 언어
C 언어 : B언어에 비해 더 좋은 언어의 의미로 B 다음인 C를 따서 C언어
1970년대에 개발되어, B언어 기능에 자료형 데이터 타입(변동성)을 추가하고, 자료 구조(분류통)에 담을 수 있는 언어.
Java 언어 ☕️
어디서나 마시는 커피처럼 어디서나 동작 가능한 자바 커피에서 이름을 따서 만든 Java 언어..
1990년대에 발표되었다. C언어 기능에 여러 기기에서 실행 가능하도록 도와주는 공통 실행환경(*JVM),
데이터와 메서드를 담는 클래스를 통해 객체를 만들 수 있는 언어.
*JVM 은 자바 공동 실행환경. 어떤 OS든 대부분의 운영체제(Window, Android, iOS, Linux..)에서 동작이 가능하게 하는 메트리스 토퍼 역할
역사를 통해 정리하는 Java 언어의 기능
-> Java는 A언어의 기능 + B언어의 기능 + C언어의 기능에 Java 언어의 기능을 추가
Java 를 배워야하는 이유는... 💭
- Java는 공통 실행환경(JVM)이 있어 여러 기기에서 실행 가능
- 여러 기기의 운영 체제에서 실행 가능
- 앱 개발에 적합 - Java는 세상과 닮아있는 개발 언어라 코드를 이해하기 쉬워서 유지 보수가 수월하다.
- Java 클래스를 통해 객체를 만든다. - Java는 안정성이 높아 프로그래밍 오류를 방지하고 보안상 안전
- 대규모 앱 개발이 가능
네트워크 및 데이터베이스 연결 및 동신 등의 작업을 처리하는 API 제공 - java를 배우면 다양한 개발 도구와 라이브러리를 사용
앱 개발에 필요한 작업을 보다 쉽게 처리
JVM
Java Virtual Machine "자바 가상 머신"
가상 머신 : 가상의 기기를 만들어 줌.
여러가지 기기 위에 Java 프로그램을 실행시킬 수 있는 가상의 기기를 만든다.
어떤 장비든 JVM을 깔아주면 Java가 실행 환경이 됨!
JVM 구성
바이트 코드
Java 프로그램 변환 코드 : 내가 작성한 코드가 운영체제가 읽을 수 있는 코드로 *Java 컴파일러가 변환한 코드
*Java 컴파일러 - 입력한 Java 코드를 운영체제가 읽을 수 있는 바이트 코드(.class)로 변환하는 변환기
인터프리터
Java.class 코드 해석기 : 운영체제가 읽은 바이트 코드를 기기가 실행할 수 있는 기계어로 번역
JIT 컴파일러
빠른 Java. 코드 해석기 : 인터프리터의 효율을 높여주는 서포터 해석기
메모리 영역
Java 데이터를 저장하는 영역 : 운영체제로부터 JVM이 할당받은 메모리 영역
클래스 로더
Java.class 바이크 코드를 메모리 영역에 담는 운반기 : JVM으로 class(바이트코드)를 불러와서 메모리에 저장
가비지 컬렉터
Java 쓰레기 청소기 : 메모리 영역에서 안 쓰는 데이터를 주기적으로 흡수해가는 청소기
Java 개발환경 구성 🗃
- JRE (Java Runtime Encironment) 자바 실행 환경 설치
.class 파일만 실행 가능 / JDK가 javac 명령을 통해 .java 파일을 실행 가능한 .class 파일로 변환 - JDK (Java Development Kit) 자바 개발 키트 설치
.java 파일을 .class 파일로 변환해주는 Java Complier(javac) 기능 / 코드를 디버깅하는 jdb 기능 - JDK 디버깅 기능 : 개발한 코드를 한 줄씩 객체와 메소드를 수행하면서 변수들도 변하는 과정을 볼 수 있도록
코드를 따라가면서 변수를 볼 수 있는 디버깅 기능을 제공
코드 해석하기
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
- public class Main {
public : 클래스 경로 외부에서 실행시킬 수 있다고 표시한 "접근 제어자"
+ 클래스 경로 외부에서 호출 못하도록 막는 "접근 제어자" private protected
class : 객체를 만드는 클래스라고 선언
Main : 클래스 명 (파일명과 일치해야함. 바이트코드 변환했을 때 파일 확장명 .class 와 일치) - public static void main(
public : 외부에서 실행시킬 수 있다고 표시한 "접근 제어자"
static : 바이트코드로 변환할 때 미리 정의되는 메서드 표기
-> 앱 실행 시 한 번만 정의되며 static 메서드 또는 변수(데이터)끼리만 호출 가능.
void : 메서드의 응답 값을 정의하는 곳인데 void는 응답할 값이 없다는 뜻
-> int 정수, char 문자, string 문자열 etc. - (String[ ] args)
메서드가 시작될 때 넘겨받을 데이터(변수)
String[ ] : 문자열 여러 개 데이터 타입
args : 문자열 여러 개 데이터의 이름 (사용자가 정의한 값 아무거나 써도 됨) - psvm : public static void Main
sout : System.out.println
🍽 변수와 상수 🥗
🍽변하는 것과 변하지 않는 것🥗
저장 공간의 선언
Java 프로그램에서 값을 다룰 때 저장 공간의 선언이 필요
선언할 때 저장 공간에 담을 값의 타입과 이름을 명시.
- 값의 타입 : 저장공간(그릇)의 종류
- 값의 이름 : 저장 공간(그릇)의 이름
int number; // number 라는 이름의 int(숫자)타입의 저장공간을 선언
String name; // name 이라는 이름의 String(문자열)타입의 저장공간을 선언
값을 저장하기.
1. 선언과 동시에 저장. 초기화
2. 선언 이후에 값을 저장. 덮어쓰기
int number = 10; // 1. 선언과 동시에 값을 저장공간에 저장 (=초기화)
number = 11; // 2. 선언 이후에 다른값을 저장공간에 저장
변수 : 변하는 저장 공간 🍽
접시에 자유롭게 먹을 음식을 담았다가 먹고 또 다른 음식 담고.. 반복
- Java 프로그램에서 저장하는 대부분의 값은 변수
- '수' = 하나의 값을 저장할 수 있는 저장 공간을 의미
- "저장 공간"은 "변하는 값"에 따라 의미에 맞게 저장하고 있는 값이 달라질 수 있음.
- 저장 공간에 변수명을 붙여 필요한 값을 저장.
- 변수는 저장되는 값의 형태에 따라 여러가지 모습을 지님.
int number = 10; // 1. 변수로 선언 및 초기화
number = 11; // 2. 변수의 값을 바꾼다. (덮어쓰기)
상수 : 변하지 않는 저장 공간 🥗
그릇에 담긴 샐러드를 다 먹을 때까지 다른 음식을 담을 수 없다.
- Java 프로그램에서 변하지 않는 값을 변하지 않는 저장 공간에 저장.
- "변하지 않는 저장 공간"이라는 말은 저장 효율을 위해 "변하지 않을 값"을 따로 저장하는 공간이 있다는 뜻.
- 상수는 저장되는 값의 형태에 따라서 여러 가지 모습을 지님.
final int number = 10; // 1. 상수로 선언 (데이터 타입 앞에 final 을 붙이면 됨!)
number = 11; // e2. 변수의 값을 바꾸려고하면 에러가 남!
변수의 종류.Type
: 저장 공간에 담을 수 있는 데이터 종류.
1. 기본형 변수 : boolean
True / False 값 저장
boolean flag = true; // 1. 논리형 변수 boolean 으로 선언 및 True 값으로 초기화
flag = false; // 2. False 값으로도 저장 가능.
2. 문자형 변수 : char
'A', '1'과 같은 문자 하나만 저장
char alphabet = 'A'; // 문자 하나를 저장
3. 정수형 변수 : byte, short, int, long
0, 1, 79, 547, 3682... 와 같은 정수형 숫자 값을 저장
정수형 변수 표현 범위
각 변수 표현 범위를 넘는 숫자를 넣게 되면 오버플로우 발생.
해당 숫자를 출력하면 입력값과 다른 값으로 표현됨. (입력한 값보다 작거나, 음수인 값)
버그를 방지하기 위해 각 변수의 표현 범위를 잘 알아야 한다.
byte byteNumber = 127; // byte 는 -128 ~ 127 범위의 숫자만 저장
short shortNumber = 32767; // short 는 -32,768~32,767 범위의 숫자만 저장
int intNumber = 2147483647; // int 는 -21억~21억 범위의 숫자만 저장
long longNumber = 2147483647L; // long 은 숫자뒤에 알파벳 L 을 붙여서 표기하며 매우 큰수를 저장
정수형 리터럴 구분 값(리터럴 = 데이터 값)
int 와 long의 데이터 값(리터럴)을 구분하기 위한 구분자로 long으로 담을 숫자 뒤에 L을 붙인다.
이런 식으로 데이터 값(리터럴) 뒤에 붙이는 구분 값을 **“접미사”**라고 부른다.
기본형 변수의 저장 가능한 숫자 범위가 커지는 이유💬
1byte 단위로 데이터를 저장할 때
각각의 정수형 변수들은 byte를 더 많이 써서 큰 수를 저장할 수 있도록 구현한다.
4. 실수형 변수 : float, double
0.132, 0.587429 와 같은 소수점 실숫값을 저장
실수형 변수의 표현 범위
실수도 동일하게 각 변수 표현 범위를 넘는 숫자를 넣게 되면 오버플로우가 발생하고,
해당 숫자를 출력해 보면 입력값과 다른 값으로 표현된다.
특히, 실수는 표현 범위가 매우 넓어서 정수형 변수에서 담지 못할 수 있음!
float floatNumber = 0.123f; // float 는 4byte 로 3.4 * 10^38 범위를 표현하는 실수값
double doubleNumber = 0.123123123; // double 은 8byte 로 1.7 * 10^308 범위를 표현하는 실수값
float : "부동"의 의미. 소수점이 움직인다는 의미의 *부동 소수점 방식으로 숫자를 저장.
*부동 소수점 방식 : 가수와 지수를 구분해서 저장하고 이 값을 곱한 값을 저장하는 방식.
float은 long 보다 더 넓은 범위를 표현할 수 있다.
long longNumber = 3.14f; // long < float 자동 형변환 불가
실수형 리터럴 구분 값(리터럴 = 데이터 값)
float 와 double의 데이터 값(리터럴)을 구분하기 위한 구분자로 float으로 담을 숫자 뒤에 f를 붙인다.
float는 소수점 7자리까지, double은 소수점 16자리까지 저장 가능하다.
5. 참조형 변수
String : "I love Apple. ", "안녕하세요, 만나서 반갑습니다. " 과 같은 문장을 저장
String message = "Hello World"; // 문자열을 저장한다.
Object, Array, List : 객체, 배열, 리스트와 같은 단일 저장공간에 담을 수 없는 값을 저장.
List<int> alphabet = [0,1,2,3]; // 기본형 변수 여러개를 저장한다.
래퍼 클래스(Wrapper Class) : 기본형 변수를 클래스로 한번 랩핑(감싸는) 변수
기본형 변수 타입명에서 첫 글자를 대문자로 바꾸어서 래퍼 클래스를 정의해준다.
박싱 VS 언박싱
- 박싱 : 기본 타입에서 래퍼 클래스 변수로 변수를 감싸는 것
- 언박싱 : 래퍼 클래스 변수를 기본 타입 변수로 가져오는 것
// 박싱 VS 언박싱
// 박싱
// Integer 래퍼 클래스 num 에 21 의 값을 저장
int number = 21;
Integer num = new Integet(number);
// 언박싱
int n = num.intValue(); // 래퍼 클래스들은 inValue() 같은 언박싱 메서드들을 제공해준다.
기본 타입
|
래퍼 클래스
|
byte
|
Byte
|
short
|
Short
|
int
|
Integer
|
long
|
Long
|
float
|
Float
|
double
|
Double
|
char
|
Character
|
boolean
|
Boolean
|
💬 래퍼 클래스를 왜.. 쓸까?
클래스는 객체지향 언어인 Java 핵심 기능이다. 클래스로 변수를 관리하면 객체지향의 많은 기능을 사용할 수 있게 된다!
ASCII code
저장 공간에 저장하는 값은 0, 1을 통한 숫자 값이며, 숫자를 문자로 매핑해서 표현한다.
Java는 아스키코드라는 규칙으로 문자를 저장하고 있다.
숫자 int 를 문자 char 로 매핑해서 표현함!
// 숫자 -> 문자
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int asciiNumber = sc.nextInt();
char ch = (char)asciiNumber; // 문자로 형변환을 해주면 숫자에 맞는 문자로 표현된다.
System.out.println(ch);
}
}
// 입력
97
// 출력
a
// 문자 -> 숫자
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char letter = sc.nextLine().charAt(0); // 첫번째 글자만 받아오기위해 charAt(0) 메서드를 사용한다.
int asciiNumber = (int)letter; // 숫자로 형변환을 해주면 저장되어있던 아스키 숫자값으로 표현된다.
System.out.println(asciiNumber);
}
}
// 입력
a
// 출력
97
문자와 문자열의 차이점
선언 관점에서 차이점
1. 문자 (char)
문자 한 개만 저장하며 따옴표를 사용하여 값을 지정 (ex. 'A')
char alphabet = 'A'; // 문자 하나를 저장한다.
2. 문자열 (String)
문자 여러 개를 문장 형태로 저장하며 쌍따옴표를 사용하여 범위를 지정. (ex. "ABCEDFG")
String message = "Hello World"; // 문자열을 저장한다.
저장 관점에서 차이점
1. 문자 (char)
문자 뒤에 \0(널문자)가 없다.
- 1 byte만 쓰기 때문에 끝을 알아서 데이터만 저장하면 된다.
2. 문자열 (String)
문장 끝에 \0(널문자)가 함께 저장된다.
- 몇 개의 byte를 쓸지 모르기 때문에 끝을 표시해야 한다.
참조형
참조형 변수 = 주소형 변수
다른 기본형 변수가 실제 값을 저장하는 저장 공간이라면,
참조형 변수는 실제 값이 아닌 원본 값의 주솟값을 저장한다.
- 기본형 변수 : 원본 값이 Stack 영역에 있다.
- 참조형 변수 : 원본 값이 Heap 영역에 있다.
Stack 영역에는 따로 저장 해둔 원본 값의 Heap 영역 주소를 저장한다.
Stack 영역 vs Heap 영역
- Stack의 경우에는 정적으로 할당된 메모리 영역이다.
- 그래서, 크기가 몇 byte 인지 정해져 있는 기본형 변수를 저장한다.
- 추가로, 크기가 정해져 있는 참조형 변수의 주솟값도 저장한다.
- Heap의 경우에는 동적으로 할당된 메모리 영역이다.
- 그래서, 크기가 계속 늘어날 수 있는 참조형 변수의 원본을 저장한다.
입력 : Java 프로그램에서는 기본적으로 System.in 객체의 next( ) 명령을 사용해서 입력을 받는다.
Scanner sc = new Scanner(System.in); // Scanner 객체를 new 명령어로 생성한다.
String input = sc.next(); // sc(Scanner)의 .next(); 를 실행하면 input 변수에 입력한 글자를 받을 수 있다.
출력 : Java 프로그램에서는 기본적으로 System.out 객체의 println( ) 명령을 사용해서 입력을 받는다.
Scanner sc = new Scanner(System.in);
String input = sc.next();
System.out.println("입력값 : " + input); // 입력한 글자를 출력한다.
// 실행 결과
{입력}
입력값 : {입력}
비트 & 바이트
Byte는 8개의 Bit로 구성되어 있다.
- Bit
- Bit(비트)는 0,1 형태의 2진수 데이터로써 컴퓨터가 저장(표현) 할 수 있는 최소 단위
- 정수형 값은 10진수 숫자(0~10범위의 숫자)이며 2진수(0~1범위) Bit로 저장(표현)
- 4개의 Bit로 16진수 숫자(0~F(16) 범위의 숫자)를 2진수(0~1범위) Bit로 저장(표현)
- Byte = 8 Bit
- Byte(바이트)는 8개의 Bit(비트)로 구성되어 있다.
- 1 Byte 내에서 숫자 변수는 Bit 2진수를 10진수로 저장(표현)을 한다.
- 10진수로는 0~255(2의8승)까지 저장(표현) 한다.
- 1 Byte 내에서 문자 변수의 경우만 Bit 2진수를 16진수로 저장(표현) 한다.
변수 타입 바꾸기_형변환
프로그래밍을 하다보면 문자열로 입력받은 변수를 숫자로 변환해서 계산을 하고 싶은 경우,
문자열에 숫자 값을 추가하고 싶은 경우... etc.
어떤 변수형을 다른 형으로 변환이 필요한 경우가 많다.
형변환은 주로 기본형 변수인 정수 ↔ 실수 ↔ 문자 사이에서 일어난다.
정수 ↔ 실수 간에 변환할 때는 ({원하는 타입}) 명령을 통해 변환이 가능하다. 캐스팅(강제 형변환)
Double, Float to Int
(Int) 캐스팅 방식으로 실수를 정수로 치환한다. 이때 실수형의 소수점 아래 자리는 버려진다.
double doubleNumber = 10.101010;
float floatNumber = 10.1010
int intNumber;
intNumber = (int)doubleNumber; // double -> int 형변환
intNumber = (int)floatNumber; // float -> int 형변환
Int to Double, Float
(Double, Float) 캐스팅으로 정수형을 실수형으로 변환한다.
int intNumber = 10;
double doubleNumber = (double)intNumber; // int -> double 형변환
float floatNumber = (float)intNumber; // int -> float 형변환
자동 형변환
형변환을 직접적으로 캐스팅하지 않아도 자동으로 형변환 되는 경우.
프로그램 실행 도중에 값을 저장하거나 계산할 때 자동으로 타입 변환이 일어난다.
자동 타입 변환은 작은 크기의 타입에서 큰 크기의 타입으로 저장될 때 큰 크기로 형변환이 발생한다.
변수 타입별 크기 순서
byte(1) → short(2) → int(4) → long(8) → float(4) → double(8)
byte byteNumber = 10;
int intNumber = byteNumber; // byte -> int 형변환
System.out.println(intNumber); // 10
char charAlphabet = 'A';
intNumber = charAlphabet; // char -> int 형변환
System.out.println(intNumber); // A의 유니코드 : 65
intNumber = 100;
long longNumber = intNumber; // int -> number 형변환
System.out.println(longNumber); // 100
intNumber = 200;
double doubleNumber = intNumber; // int -> double 형변환
System.out.println(doubleNumber); // 200.0 (소수점이 추가된 실수출력)
작은 크기의 타입이 큰 크기의 타입과 계산될 때 자동으로 큰 크기의 타입으로 형변환이 발생한다.
int intNumber = 10;
double doubleNumber = 5.5;
double result = intNumber + doubleNumber; // result 에 15.5 저장됨 (int -> double)
intNumber = 10;
int iResult = intNumber / 4; // iResult 에 2 저장됨 (int형 연산 -> 소수점 버려짐)
intNumber = 10;
double dResult = intNumber / 4.0; // dResult 에 2.5 저장됨 (double형 연산 -> 소수점 저장)
🔥 자동 형변환 vs 강제 형변환
- 작은 타입 > 큰 타입 형변환 시 (자동 형변환)
- 더 큰 표현 범위를 가진 타입으로 변환되는 것이라 값의 손실이 없다.
- 값의 손실 없이 변환이 가능하기 때문에 컴파일러가 자동으로 형변환을 한다.
- 큰 타입 > 작은 타입 형변환 시 (강제 형변환 = 캐스팅)
- 더 작은 표현 범위를 가진 타입으로 변환된는 것이라 값의 손실이 생긴다.
- 값의 손실이 생기기 때문에 자동으로 형변환을 해주지 않고 개발자가 선택하여 형변환을 한다.
*자바 강의의 완벽한 숙지를 위해 강의 자료를 정리한 내용
TIL 10월 8일
'TIL (ToDay I LearNEd) > Java' 카테고리의 다른 글
Java 문맥 구성과 데이터 관리 (연산자, 조건문, 반복문, 배열, 컬렉션) (0) | 2024.10.20 |
---|---|
Java의 기본 개념 (1) | 2024.10.14 |
Java_String format 형식 (0) | 2024.10.10 |
Intellij : 실행 후 Project 빌드 오류 (0) | 2024.09.11 |
Java의 작동 원리와 장점 (0) | 2024.09.09 |