코드스테이츠/section1

코드스테이츠 1주차 - JAVA(1) 기초

강예은 2023. 2. 28. 22:06

public class Main { … }

접근 허용 범위가 public인 Main이라는 이름의 클래스를 정의하겠다.

 

public static void main(String[] args) { … }

 

 

메서드

어떤 기능을 하는 코드를 묶음으로 묶은 것을 의미합니다. 즉, 메서드는 어떠한 기능을 수행하기 위한 일련의 코드들의 집합체입니다.

 

엄밀히 말하면, 이 설명은 ‘함수’의 개념에 가깝습니다. 함수와 메서드의 관계는 다음과 같습니다.

함수 : 특정 기능을 수행하는 코드들을 묶은 것

메서드 : 클래스 내에 포함되어 있는 함수

함수와 메서드의 의미를 구분하자면 위와 같이 구분할 수 있습니다. 하지만, 자바는 객체지향 언어이며, 모든 코드를 클래스 내에 작성하기 때문에 보통 함수라는 용어보다는 메서드라는 용어를 사용합니다.

 

데이터를 입력 받아 해당 데이터에 일련의 처리를 가함으로써 만들어낸 결과값을 반환하는 것

‘반환한다(return)’의 의미가 잘 와닿지 않을 수 있습니다. ‘반환한다’는 것은 메서드 내부의 코드가 만들어낸 결과값을 내보내는 것이라고 생각하시면 됩니다.

 

메서드란, ‘어떤 기능을 수행하기 위한 코드들을 묶어놓은 것’이며, 여기에서 ‘어떤 기능을 수행한다’는 것은 데이터를 입력받아 입력 받은 데이터에 일련의 처리를 가한 후, 그 결과값을 반환하는 것을 의미한다.

 

main 메서드는 자바로 작성한 소스 코드 파일을 실행하면 가장 먼저 실행되는 메서드입니다. 즉, 자바 애플리케이션을 실행하면 main 메서드 내부의 코드부터 코드의 흐름이 시작됩니다. 이처럼 프로그램이 실행될 때 가장 먼저 실행되는 메서드 또는 함수를 진입점 함수라고 합니다.

자바에서 main 메서드는 진입점 함수이며, 자바로 어떤 소스 코드를 작성할 때 반드시 main 메서드가 있어야 하고, main 메서드로부터 코드의 흐름이 시작됩니다.

 

  • 클래스 이름은 임의로 정해도 됩니다. 여기에서는 Test라고 클래스의 이름을 붙이겠습니다.
  • psvm + 엔터를 입력하면 main() 메서드가 자동 완성됩니다

 

변수(Variable)

값을 저장할 수 있는 메모리 공간을 확보하고, 사람이 식별할 수 있는 이름을 붙인 것

 

변수에 값을 저장하는 것을 할당 또는 대입이라고 합니다. 변수에 값을 할당하는 방법은 간단합니다. 대입 연산자 =를 아래 예제와 같이 활용하면 됩니다.

대입 연산자는 말 그대로 어떤 값을 변수에 대입 또는 할당시켜주는 연산자를 의미합니다. 좌항 = 우항;과 같은 형식으로 사용하며, 우항에는 값이, 좌항에는 변수가 위치해야 합니다.

 

변수를 선언하고 나서 처음으로 값을 할당하는 것을 초기화라고 합니다. 그리고, 초기화가 이루어진 후에 다시 다른 값을 할당하는 것을 재할당이라고 합니다.

여기에서 변수가 왜 변수라고 불리는지 그 이유를 알 수 있습니다. 즉, 재할당이 가능하다는 것은 저장하고 있는 값이 변할 수 있다는 것을 의미합니다. 이처럼 저장하고 있는 값이 바뀔 수 있는 메모리 공간을 변수라고 부릅니다.

마지막으로, 변수를 선언하면서 동시에 초기화할 수도 있습니다.

변수 명명 규칙

자바에서 변수명은 일반적으로 카멜 케이스(camelCase)를 사용합니다. 카멜케이스란 낙타 등 모양을 닮았다고 해서 붙여진 이름으로, 두 번째 단어부터 대문자로 시작해 구분합니다.

변수명으로 영문자, 숫자, _, $를 사용할 수 있으며, 영문자는 대소문자가 구별되어 인식됩니다. 즉, aA는 다른 문자로 인식됩니다.

숫자로 시작하는 변수명은 사용할 수 없습니다.

자바에서 이미 사용 중인 예약어(reserved word)는 변수명으로 사용할 수 없습니다.

변수명은 사용 목적에 맞게 작명하는 것이 중요합니다. 잘 동작한다고 해서 반드시 잘 짠 코드라고 할 수는 없습니다. 좋은 코드는 잘 동작할 뿐만 아니라, 사람에게도 잘 읽히는 코드를 의미합니다.

읽기 좋은 코드는 잘 지은 변수명에서 시작한다는 것을 기억하세요.

 

상수(Constant)

final이라는 키워드를 사용해 선언할 수 있으며, 관례적으로 대문자에 언더바(_)를 넣어 구분하는 SCREAMING_SNAKE_CASE를 사용합니다.

상수를 사용하는 이유

  • 프로그램이 실행되면서 값이 변하면 안되는 경우
    • 프로그래머가 실수로 상수에 값을 재할당하고자 하면 에러가 발생하여 실수를 방지할 수 있습니다.

 

  • 코드 가독성을 높이고 싶은 경우
    • 상수를 사용하면 값을 저장하고 있는 상수명으로 값을 사용할 수 있기 때문에 코드 가독성이 향상됩니다.

 

  • 코드 유지관리를 손쉽게 하고자 하는 경우
    • 여러분들이 계산기 프로그램을 만들었으며, 소스 코드에서 원주율이 필요한 곳에 모두 숫자값 3.14를 그대로 사용했다고 가정합시다. 만약, 여러분이 계산의 정밀도를 높이기 위해 원주율을 3.14159로 변경해야 한다면, 기존의 3.14가 사용된 모든 코드를 찾아 일일이 수정해주어야 합니다. 반면, 상수를 사용하면 상수에 할당할 값만 3.14159로 바꾸어주면 됩니다.

타입

타입은 어떤 값의 유형 및 종류를 의미하며, 타입에 따라 값이 차지하는 메모리 공간의 크기와, 값이 저장되는 방식이 결정됩니다.

  1. 값이 차지하는 메모리 공간의 크기
    • 예를 들어, 정수형 타입의 데이터는 4byte, 문자형 타입의 데이터는 1byte입니다.
  2. 값이 저장되는 방식
    • 타입은 저장하고자 하는 값을 그대로 저장하는 기본타입과, 저장하고자 하는 값을 임의의 메모리 공간에 저장한 후, 그 메모리 공간의 주소를 저장하는 참조타입으로 분류됩니다.
  • 기본 타입(primitive type)
    • 값을 저장할 때, 데이터의 실제 값이 저장됩니다.
    • 정수 타입(byte, short, int, long), 실수 타입(float, double), 문자 타입(char), 논리 타입(boolean)

 

  • 참조 타입(reference type)
    • 값을 저장할 때, 데이터가 저장된 곳을 나타내는 주소값이 저장됩니다.
    • 객체의 주소를 저장, 8개의 기본형을 제외한 나머지 타입

리터럴

사전적으로 리터럴(Literal)은 ‘문자 그대로의'라는 뜻을 가집니다. 프로그래밍에서 리터럴이란 문자가 가리키는 값 그 자체를 의미합니다.

 

리터럴을 사용할 때 알아두어야 하는 사항 두 가지

 

  • float 타입의 변수에 실수형 리터럴을 할당할 때, 리터럴 뒤에 접미사 f를 붙여주어야 합니다.
  • long 타입의 변수에 정수형 리터럴을 할당할 때, 리터럴 뒤에 접미사 L을 붙여주어야 합니다.
    • 소문자 l을 붙여도 되지만, 숫자와의 혼동을 방지하기 위해 보통 대문자 L을 사용합니다.

실수형 리터럴은 아래와 같이 사용할 수 있습니다. 이 때, double형 리터럴에는 접미사 d를 붙여도, 붙이지 않아도 되지만, float형 리터럴에는 반드시 접미사 f를 붙여주어야 합니다.

컴퓨터에서 실수를 저장할 때는 부동소수점 표현 방식으로 저장하는데, 이러한 방식은 효율적이지만 약간의 오차를 갖습니다.

이 오차는 실수를 더 정밀하게 표현할수록 줄어듭니다. 여기서 얼마나 실수를 정밀하게 나타낼 수 있는지를 정밀도라고 하는데, 정밀도는 데이터 타입의 크기가 클수록 높아집니다.

따라서 double형은 float형보다 정밀도가 더 높습니다.

정리하면, double형은 float형보다

  1. 더 큰 실수를 저장할 수 있습니다.
  2. 더 정확하게 저장할 수 있습니다.
  • 오버플로우
    • 자료형이 표현할 수 있는 범위 중 최대값 이상의 값을 표현한 경우 발생합니다.
    • 최대값을 넘어가면 해당 데이터 타입의 최소값으로 값이 순환합니다.
    • 예 : 어떤 값이 byte형이고, byte형의 최대값인 127을 값으로 가지는 경우, 이 값에 1을 더하면 128이 되는게 아니라, 최소값인 -128이 됩니다.

 

  • 언더플로우
    • 자료형이 표현할 수 있는 범위 중 최소값 이하의 값을 표현한 경우 발생합니다.
    • 최소값을 넘어가면 해당 데이터 타입의 최대값으로 값이 순환합니다.
    • 예 : 어떤 값이 byte형이고, byte 형의 최소값인 -128을 값으로 가지는 경우, 이 값에 1을 빼면 -129가 되는게 아니라, 최대값인 127이 됩니다.

실수형에서도 오버플로우와 언더플로우가 발생합니다. 다만, 오버플로우와 언더플로우가 발생했을 때의 결과가 다릅니다.

  • 오버플로우
    • 값이 음의 최소 범위 또는 양의 최대 범위를 넘어갔을 때 발생하며, 이 때 값은 무한대가 됩니다.
  • 언더플로우
    • 값이 음의 최대 범위 또는 양의 최소 범위를 넘어갔을 때 발생하며, 이 때 값은 0이 됩니다.

 

논리 타입

논리 타입의 종류는 boolean형 한가지 뿐입니다. boolean형은 참 또는 거짓을 저장할 수 있는 데이터 타입으로, 오직 true 혹은 false를 값으로 가집니다.


단순히 참과 거짓을 표현하기 위해서는 1bit만 있으면 되지만, JVM이 다룰 수 있는 데이터의 최소 단위가 1byte이기 때문에 boolean형은 1byte(8bit)의 크기를 가집니다.

 

문자 타입

문자 타입은 2byte 크기의 char형 오직 하나만 있습니다.

문자 타입 변수를 선언하면 해당 변수에 오직 하나의 문자형 리터럴을 저장할 수 있습니다.

문자형 리터럴을 작성할 때에는 반드시 큰 따옴표(””)가 아닌 작은 따옴표(’’)를 사용하여야 합니다. 큰 따옴표를 사용한 리터럴은 문자형 리터럴이 아니라 문자열 리터럴로 인식되기 때문입니다.

참고로, 자바에서 문자형과 문자열은 다릅니다.

 

자바는 유니코드로 문자를 저장합니다. 유니코드는 전 세계의 모든 문자를 컴퓨터에서 일관되게 다루기 위한 국제 표준으로, 각 문자에 숫자 코드 번호를 부여한 것입니다. 따라서, char letter1 = ‘a’;와 같이 문자형 리터럴을 문자형 변수에 할당하면 letter1에는 영문자 a의 유니코드 숫자값이 저장됩니다.

숫자를 문자형 변수에 할당할수도 있습니다. 아래 예제처럼 숫자를 문자형 변수에 할당하면, 해당 숫자가 그대로 저장되지만, 나중에 변수를 참조할 때, 즉 변수의 값을 읽어올 때 해당 변수가 저장하고 있는 숫자값을 유니코드로 인식하여 해당 숫자와 일치하는 코드를 가진 문자로 변환해줍니다.

타입 변환

boolean을 제외한 기본 타입 7개는 서로 타입을 변환할 수 있으며, 자동으로 타입이 변환되는 경우도 있고, 수동으로 변환해주어야만 하는 경우도 있습니다.

 

자동 타입 변환

아래 두 경우에는 타입이 자동으로 변환됩니다.

  1. 바이트 크기가 작은 타입에서 큰 타입으로 변환할 때 (예 : byte → int)
  2. 덜 정밀한 타입에서 더 정밀한 타입으로 변환할 때 (예 : 정수 → 실수)

수동 타입 변환

차지하는 메모리 용량이 더 큰 타입에서 작은 타입으로는 자동으로 타입이 변환되지 않습니다. 이때 더 큰 데이터 타입을 작은 데이터 타입의 변수에 저장하기 위해서는 수동으로 타입을 변환해주어야만 합니다. 이를 캐스팅(casting)이라고 합니다.

수동으로 타입을 변환할 때에는 캐스팅 연산자 ()를 사용하며, 캐스팅 연산자의 괄호 안에 변환하고자 하는 타입을 적어주면 됩니다.

위 예제에서 intValue가 저장하고 있는 int형의 값 128을 byte형으로 캐스팅하여 byte형 변수 byteValue에 할당해주었습니다. byte형의 표현 범위는 -128 ~ 127이므로, 128을 byte형으로 변환하면 표현 범위를 벗어나게 되어 오버플로우가 발생합니다. 따라서 최종적으로 저장되는 값은 -128이 됩니다.

타입 변환은 예전에는 중요한 개념이었지만, 메모리 용량이 넉넉해진 지금은 일반적으로 정수는 int 또는 long, 실수는 double로 사용하기 때문에 예전에 비해 수동 타입 변환의 사용 빈도가 많이 줄었습니다. 따라서 지금은 ‘타입 변환이란 이런 것이구나’ 정도로만 이해해주시면 됩니다.

 

String이란? 

다른 타입들과 다르게 문자열만 클래스를 통해 다룹니다.

클래스는 그 자체로 타입으로 사용될 수 있으며, 연관된 기능들을 묶을 수 있습니다.

String 클래스는 문자열 타입으로 사용되며, 문자열과 관련된 유용한 메서드들을 가지고 있습니다. "문자열은 String 클래스를 통해 다루어지고, 그 안에 있는 메서드들을 통해 여러 문자열 관련 메서드들을 사용할 수 있구나” 정도로만 이해

 

String 타입의 변수 선언과 할당

기본적으로 String 타입은 큰따옴표("")로 감싸진 문자열을 의미합니다.

“클래스는 일종의 거푸집이며, 그 거푸집을 통해서 찍어낸 것이 인스턴스다. 그리고, 클래스로 인스턴스를 찍어내고자 할 때 new 연산자를 사용한다.

어떤 클래스를 통해 인스턴스를 생성하면 해당 인스턴스의 타입은 자신을 생성해낸 클래스를 타입으로 가집니다. 그러므로, String 클래스를 통해 만들어진 인스턴스는 String 타입의 변수에 할당할 수 있습니다.

 

 

  • String 타입의 변수는 String 변수명;으로 선언할 수 있다.
  • 선언한 변수에 문자열을 할당하는 방법은 두 가지가 있다.
    1. 문자열 리터럴을 할당하는 방법 : 변수 = “문자열”;
    2. String 클래스의 인스턴스를 생성하여 할당하는 방법 : 변수 = new String(”문자열”);

 

심화 학습

문자열 리터럴을 직접 할당하는 방식이든, String 클래스의 인스턴스를 생성하여 할당하는 방법이든 공통적으로 참조 타입의 변수에 할당됩니다. 실제 문자열의 내용을 값으로 가지고 있는 것이 아니라, 문자열이 존재하는 메모리 공간 상의 주소값을 저장하고 있습니다.

 

그러나, 문자열을 출력해보면 주소값이 아니라 문자열의 내용이 출력됩니다.

String name1 = "Kim Coding";
String name2 = new String("Kim Coding");

System.out.print(name1); // "Kim Coding"
System.out.print(name2); // "Kim Coding"

 

이는 String 타입의 변수를 참조하면 String 클래스의 메서드인 toString()이 자동으로 호출되기 때문입니다. toString()이 자동으로 호출되면 String 타입의 변수가 저장하고 있는 주소값에 위치한 String 인스턴스의 내용을 문자열로 변환해줍니다.