Part1 자바 언어 기초

YunGyu Choi·2023년 5월 9일
0

이것이 자바다

목록 보기
1/3

1. 자바 시작하기

1) 프로그래밍 언어와 자바

(1) 프로그래밍 언어

프로그래밍 언어의 필요

컴퓨터는 0과 1로 이루어진 이진 코드로 이루어진 기계어를 사용한다. 따라서 컴퓨터와 사람이 소통하기 위해서는 사람의 언어와 기계어의 다리 역할을 하는 프로그래밍 언어가 필요하다.

프로그래밍 언어의 종류

  • 고급 언어
    컴퓨터와 대화할 수 있도록 만들어진 언어 중 사람이 쉽게 이해할 수 있는 언어이다.
    고급 언어로 작성된 파일은 컴퓨터가 바로 이해할 수 없기 때문에 컴파일 과정을 거쳐 기계어로 변환이 필요하다.
    ex) Java, C, C++, C#, Python
  • 저급 언어
    기계어에 가까운 언어, 대표적으로는 어셈블리어가 있다.
    어셈블리어 : 기계어를 직접 작성하는 것 보다는 사람이 이해하기 쉬운 기호로 작성한 언어로, 특정 컴퓨터 아키텍처에 사용되는 CPU명령어 집합을 가지고 있다. 어셈블리어는 컴퓨터 아키텍처가 다른 컴퓨터 간에는 호환되지 않아 이식성이 낮다.
  • 정적 언어
    컴파일 시 변수의 타입이 결정되는 언어이다. 따라서 프로그래머가 변수에 들어갈 값의 형태에 따라 직접 변수의 타입을 명시해줘야 한다.
    타입 에러로 인한 문제점을 초기에 발견할 수 있어 타입의 안정성이 높다는 장점이 있지만 매번 코드 작성시 변수형을 결정해줘야하는 번거로움도 있다.
  • 동적 언어
    런타임 시 변수의 타입이 결정되는 언어이다. 런타임까지 타입에 대한 결정을 끌고갈 수 있기 때문에 유연성이 높다는 장점이 있지만, 실행 도중에 변수에 예상치 못한 타입이 들어와 타입에러가 발생할 수 있다는 단점도 있다.

프로그래밍 언어 번역기

번역기는 프로그래밍 언어를 실행가능한 기계어로 변환해주는 프로그램을 뜻한다.

  • 컴파일러
    소스코드 전체를 분석한 후 기계어 코드로 변환하는 방식으로 번역을 수행한다. 이때 생성된 기계어 코드는 실행 파일 형태로 저장되어 나중에 필요할 때마다 실행된다. 컴파일러를 거치는 언어를 컴파일 언어라고하며 대표적으로 C, Java등이 있다. 컴파일 언어는 한 번만 번역하면 되기 때문에 실행 속도는 빠르지만 소스 코드에 수정이 가해진 경우 다시 컴파일 해야하는 번거로움과 컴파일 시간이 올래 걸리는 경우도 있어서 개발 속도는 느린 편이다.
  • 인터프린터
    반면 인터프린터는 소스 코드를 한 줄씩 읽어들여서 바로 실행하는 방식으로 번역을 수행한다. 이때 생성된 기계어 코드는 일시적으로 메모리에 저장되며, 프로그램 실행 중에 필요할 때마다 실행된다. 인터프린터를 거치는 언어를 스크립트 언어라고하며 대표적으로 Python, JavaScript등이 있다. 스크립트 언어는 실행할 때마다 번역을 해야해서 실행 속도는 한 번에 번역하는 컴파일 언어보다 느리지만 개발 속도는 컴파일 언어보다 빠르다.

(2) 자바

  • 자바 런타임 환경(JRE;Java Runtime Environment
    자바프로그램을 실행할 때 필요한 환경을 제공하는 프로그램이다. JRE에는 JVM, 클래스 라이브러리, 런타임 환경 등이 포함되어 있다.
    런타임 환경은 소프트웨어가 실행되는 환경이다. 즉, 소프트웨어가 실행될 때 필요한 라이브러리, 런타임 시스템 데이터, 메모리 등이 모두 포함된 환경이다.
  • 자바 개발 도구(JDK;Java Developmetn Kit)
    자바 프로그램을 개발하기 위해 필요한 모든 도구와 라이브러리가 포함된 패키지이다. JDK에는 Java Compiler, JVM, 클래스 라이브러리, 디버깅 도구 등이 포함되어 있다.
  • 자바 가상 머신(JVM;Java Virtual Machine)
    자바 프로그램을 실행하기 위한 가상머신이다. JVM은 운영체제나 하드웨어와 상관없이 동일한 실행환경을 제공한다. Java프로그램은 JVM에 설치된 컴퓨터에서 실행되며, JVM은 자바 바이트 코드를 해당 운영체제에서 실행가능한 기계어로 변환하여 실행한다.

자바 컴파일 과정

① 소스코드를 작성하면 파일명.java로 저장
javac 파일명.java로 컴파일
파일명.class라는 바이트 코드 파일 생성
java 파일명.java로 자바 가상 머신이 바이트 코드 파일 실행

패키지(Package)

자바는 소스 파일 및 컴파일된 바이트코드 파일을 쉽게 관리하기 위해 패키지를 사용한다. 패키지는 파일 시스템에서의 디렉토리와 비슷하다.


2. 변수와 타입

1) 변수

컴퓨터 메모리(RAM)는 수많은 번지들로 구성된 데이터 저장 공간이다. 프로그램은 데이터를 메모리에 저장하고 읽는 작업을 빈번히 수행한다. 이때 데이터를 어디에, 어떻게 저장할지 정해져 있지 않다면 메모리 관리가 무척 어려워진다. 프로그래밍 언어는 변수를 사용해 이 문제를 해결한다.
변수는 하나의 값을 저장할 수 있는 메모리 번지에 붙여진 이름이다. 변수를 통해 프로그램은 메모리 번지에 값을 저장하고 읽을 수 있다.

변수의 선언

변수를 사용하기 위해서 자바는 먼저 변수를 선언해야한다. 변수 선언은 어떤 타입의 데이터를 저장할 것인지 그리고 변수 이름이 무엇인지를 선언한다.
변수 선언은 저장되는 값의 타입과 이름만 결정한다. 선언만 이루어진 상태에서는 아직 메모리에 할당이 이루어진 것은 아니다.

변수에 대입

변수가 선언되면 대입연산자 =를 활용 하여 해당 변수에 값을 대입할 수 있다. 그리고 변수에 값이 최초로 대입될 때 메모리에 값이 저장된다.

변수 초기화

변수에 최초로 값을 대입하는 행위를 변수 초기화라고 한다.

변수 타입

변수는 선언될 때 타입에 따라 저장할 수 있는 값의 종류와 허용 범위가 달라진다. 자바는 정수, 실수, 논리값을 저장할 수 있는 기본 타입 8개를 다음과 같이 제공한다.

타입메모리 크기저장되는 값의 허용 범위
boolean1byte(8bit)ture, false
char2byte(16bit)유니코드 문자
byte1byte(8bit)-128 ~ 127
short2byte(16bit)-32,768 ~ 32,767
int4byte(32bit)-2,147,483,648 ~ 2,147,483,647
long8byte(64bit)-2^63 ~ (2^63-1)
float4byte(32bit)유효 소수 이하자리 7자리
double8byte(64bit)유효 소수 이하자리 15자리

리터럴(Literal)

코드에서 프로그래머가 직접 입력한 값이다.

2) 타입

정수 타입

변수에 대입할 정수 리터럴은 진수에 따라 작성법이 다르다. 아래는 13을 다르게 표현한 것이다.

int bin = **0b**1101; // 2진수
int oct = **0**15;	// 8진수
int deci = 13;		// 10진수
int hex = **0x**D;	// 16진수

컴파일러는 int로 간주하기 때문에 l을 붙여서 long type 임을 컴파일러에게 알려줘야 한다.

long var1 = 1000000000000;	// 컴파일 오류
long var2 = 1000000000000**l**;	// Long 타입 인식

문자 타입

하나의 문자를 작은따옴표(')로 감싼 것을 문자 리터럴이라고 한다. 문자 리터럴은 유니코드로 변환되어 저장되는데, 유니코드는 세계 각국의 문자를 0~65535 숫자로 매핑한 국제 표준 규약이다.

char var1 = 'A';	// 유니코드 65로 대입
char var2 = '가';	// 유니코드 44032로 대입 

유니코드도 정수이므로 char 타입도 정수 타입에 속한다. 따라서 char 변수에 작은 따옴표로 감싼 문자가 아니라 유니코드 숫자를 직접 대입할 수도 있다.

char var3 = 65;	//문자 'A'
char var4 = **0x**0041	// 문자 'A'

자바는 ''; 빈 문자를 대입하면 컴파일 에러가 발생한다.

실수 타입

실수 타입에는 float과 double이 있다. 그리고 '정밀도(precision)'라는 개념이 존재한다. 정밀도는 소수점 이하 숫자의 자리수를 의미한다. float의 정밀도는 6~7자리 정도이고, double의 정밀도는 15자리 정도이다. 그러나 정밀도는 상황에 따라서 떨어질 수 있다.

자바는 IEEE 754 표준에 근거해서 float타입과 double타입의 값을 부동 소수점 방식으로 메모리에 저장한다.
부동 소수점 표현은 실수를 정확하게 표현하기 위해 가수지수를 이용하여 값을 근사적으로 표현한다.

가수는 소수점 앞 또는 뒤에 있는 유효숫자를 의미한다. 예를 들어, 123.45라는 수를 부동소수점 형식으로 표현하면 1.2345 x 10^2와 같이 표현할 수 있고 이때 12345가 가수에 해당한다.

지수는 10의 몇제곱인지를 나타내는 숫자로, 가수에서 소수점의 위치를 조절하는 역할을 한다. 지수는 양수일 수도 있고, 음수일 수도 있다. 음수일 경우 소수점을 앞으로 이동시키고 양수일 경우 소수점을 뒤로 이동시킨다. 이를 지수 표기법으로 나타내면 1.2345e+2 이다.

부호는 음수인지 양수인지 결정하는 것으로 최상위 1bit가 결정한다.

실수 타입도 정수 타입의 long와 비슷한 경우가 있다. 컴파일러는 기본적으로 double로 인식하기 때문에 float 인 경우 'f'로 컴파이러에게 알려줘야 한다.

float f1 = 3.14;   //  컴파일러가 double로 인식
float f2 = 3.14**f**;  // 컴파일러가 float으로 인식

논리 타입

참과 거짓을 의미하는 논리 리터럴은 true와 false이다. 논리 리터럴은 boolean 타입 변수에 다음과 같이 대입할 수 있다. 연산식 중에서 비교 및 논리 연산의 산출값은 true 또는 false이므로 boolean 타입 변수에 다음과 같이 대입할 수 있다.

문자열 타입

작은따옴표(')로 감싼 한 개의 문자는 char타입이지만, 큰따옴표(")로 감싼 한 개의 문자나 작은따옴표(')로 감싼 여러 개의 문자들은 유니코드로 변환되지 않는다.

char var1 = "A";  	// 컴파일 에러
char var2 = 'abc';	// 컴파일 에러
char var1 = 'A';

문자들의 모임을 문자열이라 하고 문자열은 큰따옴표(")로 감싼다. 문자열을 변수에 저장하고 싶다면 String타입을 사용해야 한다.
String은 자바 기본 타입에 속하지 않는 '참조 타입'이다.

자동 타입 변환

자동 타입 변환은 말 그대로 자동으로 타입 변환이 일어나는 것을 말한다. 자동 타입 변환은 값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 대입될 때 발생한다.
기본 타입을 허용 범위 순

  • byte < short,char < int < long < float < double

정수 타입이 실수 타입으로 대입되는 경우 무조건 자동 타입 변환된다.

long longValue = 5000000000L;
float floatValue = longValue;		// 5.0e9f로 저장됨
double doubleValue = longValue;		// 5.0e9로 저장됨

char 타입의 경우 int 타입으로 자동 변환되면 유니코드 값이 int타입에 대입된다.

char charValue = 'A';
int intValue = charValue;	// 65가 저장됨

강제 타입 변환

큰 허용 범위 타입은 작은 허용 범위 타입으로 자동 타입 변환될 수 없다. 마치 큰 그릇을 작은 그릇 안에 넣을 수 없는 것과 같은 이치이다. 하지만 큰 그릇을 작은 그릇 단위로 쪼개서 한 조각만 작은 그릇에 넣는 것은 가능하다.

  • int ➡️ byte
    int intValue = 10
    byte byteValue = (byte) intValue;	// 캐스팅으로 강제 변환
  • long ➡️ int
    long longValue = 300;
    int intValue = (int) longValue;	// 강제타입 변환후 300 그대로 유지
  • int ➡️ char
    int int Value = 65;
    char charValue = (char) intValue;	// 'A'
  • 실수 ➡️ 정수
    double doubleValue = 3.14;
    int intValue = (int) doubleValue;	// 정수 부분인 3만 저장

문자열을 기본 타입으로 변환

참조 타입인 문자열을 기본 타입으로 바꾸기 위해서는 parse를 사용해야한다.
바꿀기본타입 변수명 = 바꿀기본타입.parse바꿀기본타입(문자열)과 같은 형태로 사용한다.
다만, 기본타입을 문자열로 바꾸려면 String.valueOf(기본타입)과 같은 형태로 사용한다.

  • String ➡️ byte
    String str = "10";
    byte value = Byte.parseByte(str);
  • String ➡️ short
    String str = "200";
    short value = Short.parseShort(str);
  • String ➡️ int
    String str = "300000";
    int value = Integer.parseInt(str);
  • String ➡️ long
    String str = "40000000000";
    long value = Long.parseLong(str);
  • String ➡️ float
    String str = "12.345";
    float value = Float.parseFloat(str);
  • String ➡️ double
    String str = "12.345";
    double value = Double.parseDouble(str);
  • String ➡️ boolean
    String str = "true";
    boolean value = Boolean.parseBoolean(str);
  • 기본 타입 값 ➡️ String
    String str = String.valueOf(기본 타입 값);

3) 스코프(Scope)

메소드 블록에는 다른 중괄호 {}블록들이 작성될 수 있다. 이러한 중괄호 {}블록 내에서 선언된 변수는 해당 중괄호 {}블럭 내에서만 사용이 가능하고 밖에서는 사용할 수 없다.
만약 메소드 블록 전체에서 사용하고 싶다면 메소드 블록 첫머리에 선언하는 것이 좋고, 특정 블록 내부에서만 사용된다면 해당 블록 내에서 선언하는 것이 좋다.

4) 변수 값 입출력

변수 출력

System.out.print();		// 출력
System.out.println();	// 출력하고 개행
System.out.printf("형식문자열",1 ..);  //포맷 스트링 

형식 문자열

형식설명출력형태
정수%d정수123
%6d6자리정수.왼쪽 빈자리 공백___123
%-6d6자리정수.오른쪽 빈자리 공백123___
%06d6자리 정수.왼쪽 빈자리0채움000123
실수%10.2f정수 7자리+소수점+소수2자리.왼쪽 빈자리 공백____123.45
%-10.2f정수 7자리+소수점+소수2자리.오른쪽 빈자리 공백123.45____
%010.2f정수 7자리+소수점+소수2자리.왼쪽 빈자리 0채움0000123.45
문자열%s문자열abc
%6s6자리 문자열.왼쪽 빈자리 공백___abc
%-6s6자리 문자열. 오른쪽 빈자리 공백abc___
특수문자\t탭(tab)
\n개행
%%%%
String name = "홍길동";
String job = "도적";
System.out.printf("%s는 %s이다.\n", name, job);
System.out.printf("반지름이 %d인 원의 넓이:%10.2\n",10,3.14159*10^2);

키보드 입력

키보드로부터 입력된 데이터를 읽고 변수에 저장하는 가장 쉬운 방법은 Scanner를 사용하는 것이다. Scanner 타입 변수를 선언하고, 대입연산자 =를 사용해서 new 연산자로 생성한 Scanner 객체를 변수에 대입한다.
nextLine()은 Enter키가 입력되기 전까지 블로킹(대기) 상태가 되며, Enter키가 입력되면 지금까지 입력된 모든 내용을 문자열로 읽는다.

Scanner scanner = new Scanner(System.in);
Scanner inputData = scanner.nextLine();

3. 연산자

1) 연산자 종류

부호/증감 연산자

  • 부호 연산자는 변수의 부호를 변경할 때 사용된다.

  • 주의! 정수타입(byte, short, int)의 연산 결과는 int이다.

  • 증감연산자는 ++로 1씩 증가시키거나 --로 1씩 감소시킨다.

  • ++피연산자는 피연산자의 값을 바로 1씩 증가시킨다.

  • 피연산자++는 다른 연산을 수행한 후에 피연산자의 값을 1씩 증가시킨다.

  • --또한 감소하는 것을 제외하고는 같다.

산술연산자

  • 종류 : +(더하기), -(빼기), *(곱하기), /(나누기), %(나머지)
  • 피연산자 중 더 큰 그릇을 가진 자료형을 따라간다.
  • 정확한 연산을 위해서는 정수를 사용하는 것이 좋다.
    부동소수점 연산은 정확한 값을 출력하지 못하는 경우가 존재한다.
  • 나눗셈, 나머지 연산에서 좌측 피연산자가 정수이고 우측 피연산자가 0일 경우 예외(ArithmeticException)가 발생한다. 무한대의 값을 정수로 표현할 수 없기 때문이다.
  • 하지만 0이 아닌 0.0이나 0.0f인 경우 예외가 발생하지않고 무한대(inf) or NaN이 된다.
  • 주의! inf or NaN 값을 가지고 연산을 하면 안된다. 어떤 연산을 하더라도 결과는 계속 inf와 NaN이 되기 때문이다.

오버플로우와 언더플로우

  • 오버플로우 : 타입이 허용하는 최대값을 벗어나는 것
  • 언더플로우 : 타입이 허용하는 최소값을 벗어나는 것
  • 오버플로우나 언더플로우 발생시 최대값을 벗어나면 최소값이되고,
    최소값을 벗어나면 최대값이된다.

비교연산자

  • 종류 : ==(같다), !=(다르다), >, >=, <. <=
  • 결과 : boolean 으로 반환
  • float 타입과 double 타입의 정밀도 차이로 인해 컴퓨터는 0.1과 0.1f를 다르게 본다.
  • 문자열을 비교할 땐 equals()와 !equals()를 쓴다.
boolean result1 = srt1.equals(srt2);  // 문자열이 같은지 검사
boolean result2 = !srt1.equals(srt2); // 문자열이 다른지 검사

논리 연산자

  • 종류 : &&(논리곱), ||(논리합), ^(배타적 논리합), !(부정)
  • 사용처 : 논리연산은 주로 조건문, 반복문 등에서 이용

비트 논리 연산자

  • 2진수로 저장되는 정수 타입(byte, short, int, long)만 피연산자가 될 수 있다.

비트 이동 연산자(쉬프트 연산자)

비트를 좌측 또는 우측으로 밀어서 이동시키는 연산자

  • a << b
    정수 a의 각 비트를 b만큼 왼쪽으로 이동,
    오른쪽 빈자리는 0으로 채움
    a x 2^b와 동일한 결과가 됨(2의 b제곱으로 곱한 것)
  • a >> b
    정수 a의 각 비트를 b만큼 오른쪽으로 이동,
    왼쪽 빈자리는 최상위 부호 비트와 같은값으로 채움
    a / 2^b와 동일한 결과가 됨(2의 b제곱으로 나눈것)
  • a >>> b
    정수 a의 각 비트를 b만큼 오른쪽으로 이동

대입 연산자

우측 피연산자의 값을 좌측 피연산자의 변수에 저장

삼항 조건 연산자

  • 구조
    조건식 ? 참일때 : 거짓일때

2) 연산자 우선순위

1순위 : 증감 연산자
2순위 : 산술 연산자
3순위 : 시프트 연산자
4순위 : 비교 연산자
5순위 : 비트 연산자(~만 1순위)
6순위 : 논리 연산자(!만 1순위)
7순위 : 조건(삼항) 연산자
8순위 : 대입 연산자


4. 제어문

자바 프로그램은 main()메소드의 시작 중괄호에서 끝 중괄호 까지 위에서 아래로 실행하는 흐름을 가지고 있다. 이러한 실행 흐름을 개발자가 원하는 방향으로 바꿀 수 있도록 해주는 것이 제어문이다. (제어문을 사용할 경우 다양한 실행 흐름이 생성된다.)

1) 조건문

(1) if문

조건식의 결과에 따라 블록 실해영부가 결정된다.

// if 문
if (조건식) {
	실행문
}

// else-if 문
if (조건식) {
	실행문
} else if (조건식2) {
	실행문2
} else if (조건식3) {
	실행문3
} else {
	실행문4
}

(2) switch문

if문은 true/false 두 가지만의 결과만으로 흐름을 만들어 경우의 수가 많이질 경우 복잡해 질 수 있다. 그러나 switch문은 다양한 결과로 흐름을 만들어 코드가 간결해질 수 있다.

switch(변수) {
	case1 :
    	실행문1	// 변수가 값1일 때 실행
        break;	  // 브레이크 없으면 밑으로 쭉내려감
    case2 :
    	실행문2	// 변수가 값2일 때 실행
        break;
    default:	  // case에 변수 값과 같은 값이 없으면 실행
}

2) 반복문

(1) for문

for (초기화식; 조건식; 증감식) {
	실행문 // 조건식이 true일 경우 실행
}

(2) while문

while (조건식) {
	실행문 // 조건식이 true일 경우 실행
}

(3) do-while문

do {
	실행문 // 먼저 실행한 번 하고
} while (조건식); // 조건식이 true일 경우 다시 실행

(4) break문

반복문의 실행을 중지하거나 조건문인 switch문을 종료할 때 사용

(5) continue문

반복문 블록 내부에서 continue를 만나면 바로 다음 반복여부로 스킵


profile
velog에는 이론을 주로 정리하고, 코드와 관련된 것은 Git-hub로 관리하고 있어요. 포트폴리오는 링크된 Yun Lab 홈페이지를 참고해주시면 감사하겠습니다!

0개의 댓글