프로그래밍/Java

[Java] Java기초 - (2) 기초 문법 - 변수와 리터럴

Churnobyl 2023. 10. 12. 13:17
728x90
반응형

 파이썬에 대해 어느 정도 알고 있는 상태이므로 이를 확장해서 자바의 기초 문법을 정리해보고자 한다. 우선 생각보다 전반적으로 엄청 다른 부분은 없었다. 둘 다 각 언어만의 가상 머신을 이용해 프로그램을 실행한다거나, 프로그래밍 언어가 으레 그렇듯 배열, 조건문, 반복문 등의 문법이 있고 구문도 거의 비슷하다 (자바스크립트랑 더 비슷하긴 함). 또한 둘 다 객체 지향 언어라는 점 또한 비슷하고 중요하다.

 

 다만 파이썬은 코드를 한 줄씩 읽어서 실행하는 인터프리터 언어, 자바는 전체 코드를 바이트 코드로 컴파일한 뒤 JVM으로 실행하는 컴파일 언어라는 점이나 자바는 C/C++계열 언어처럼 변수 자료형이 존재한다는 점 등이 주요한 차이점이다.


01. 변수 (Variable)

 

자바의 변수 선언

 

 자바는 변수 타입이 존재한다. 파이썬은 값의 자료형과 관계없이 변수에 들어가는 값에 따라 동적으로 메모리 공간의 크기가 할당되는 동적 타이핑 언어인 것과 달리, 자바는 문자나 숫자같은 값의 타입에 따라 값이 저장될 메모리 공간의 크기와 저장형식을 먼저 정의하고 할당된 공간에 실제 값이나, 실제 값이 저장된 공간의 레퍼런스를 넣는 정적 타이핑 언어다. 변수 선언 방식의 장단점이야 더 자세히 기술할 수 있겠지만 간단히 설명하면 파이썬은 더 편하고 자바는 더 에러 발생 가능성이 낮다.

 

 기본형 변수(Primitive Type)에는 문자형(char), 정수형(byte, short, int, long), 실수형(float, double), 논리형(boolean) 총 8가지가 있고 그외 모든 자료형은 참조형 변수(Reference Type)다. 두 자료형의 중요한 차이점은, 기본형 변수는 변수에 실제 데이터를 저장하지만 참조형 변수는 실제 데이터가 저장되어 있는 주소 즉, 레퍼런스를 갖는다는 점이다. 또 자바는 C/C++계열과 달리 참조형 변수 간의 연산을 할 수 없으므로 실제 연산에 사용되는 것은 모두 기본형 변수다.

 

 참조형 변수를 선언할 때는, 변수의 타입으로 클래스의 이름을 사용하므로 클래스의 이름이 참조형 변수의 타입이 된다. 따라서 새로운 클래스를 작성한다는 것은 새로운 참조 자료형을 만드는 셈이다.

 

 


1. 기본형 (Primitive Type)

자바의 기본 자료형

 위 그림은 자바의 기본 자료형 8가지를 나타낸 것이다. 여기서 문자형 char은 실제로 값을 정수값인 유니코드로 저장하므로 정수형과 함께 묶어서 표현하기도 한다. 또 유일하게 boolean 타입만 다른 자료형과 연산이 불가능하며, 나머지 자료형은 서로 연산이 가능하다.

 

 

 

public class App {
    public static void main(String[] args) throws Exception {
        boolean booleanType = true;

        System.out.println(booleanType);

        char charType = 'A';

        System.out.println(charType);

        byte byteType = 127;
        short shortType = 32_767;
        int intType = 2_147_483_647;
        long longType = 123123124221l;

        System.out.println(byteType);
        System.out.println(intType);
        System.out.println(longType);

        float floatType = 123.4567f;
        double doubleType = 123456789.12345678910;

        System.out.println(floatType);
        System.out.println(doubleType);
        
        final double PI = 3.141592;
    }
}
true
A
127
2147483647
123123124221
123.4567
1.2345678912345679E8

 

 위는 각 기본형 변수를 생성하고 출력하는 간단한 예제인데, 특이한 점은 long, float타입의 값 뒤에는 각각 l과 f가 붙어있다. 이는 리터럴이라고 하는 것에 접미사가 붙기 때문인데, 리터럴이란 간단히 말해서 우리가 수학적으로 알고 있는 상수와 똑같은 의미다. 즉 실제 어떤 데이터를 의미한다. 다만 프로그래밍에서 '값을 한 번 저장하면 변경할 수 없는 고유한 값을 저장하는 공간'을 상수(constant)라고 정의해 버려서 그것과 구별하기 위해 수학적인 상수(값 그 자체)를 리터럴이라고 부르는 것이다. 

 

변수 vs 상수 vs 리터럴

 

 

 위에서 언급한 것처럼 리터럴에는 접미사가 붙는다. 리터럴 또한 타입을 가지기 때문인데 아래 표와 같다. 

리터럴과 접미사

 

 자바에서 int, double형이 주로 쓰이므로 접미사를 안 붙여도 되고, long, float형을 사용할 때만 l, f를 붙여주면 된다. double에도 d라는 접미사가 있지만 생략 가능하다.

 


1.1 논리형 (boolean)

 true, false 중 하나를 저장할 수 있는 논리형으로 디폴트는 false다. 주로 yes or no, on or off 등의 논리구현에 사용된다. true/false 두 가지 값만 표현하면 되므로 사실 1bit로도 표현가능하지만, 자바에서 데이터를 다루는 최소 단위가 1byte이므로 boolean의 크기는 1byte이다.

 

public class Main {
    public static void main(String[] args) throws Exception {

        boolean lightSwitch = false;
        System.out.println(light(lightSwitch));
        lightSwitch = true;
        System.out.println(light(lightSwitch));

    }

    public static String light(boolean swi) {
        if (swi) {
            return "Light ON";
        } else {
            return "Light Off";
        }
    }
}
Light OFF
Light ON

 

 


1.2 문자형 (char)

 문자를 저장하기 위한 변수를 선언할 때 사용되며, 단 하나의 문자만을 저장할 수 있는 문자형 타입이다. 크기는 2byte이며, 문자를 저장하기 위해 사용되므로 음수를 표현할 필요가 없다. 따라서 저장할 수 있는 정수의 범위는 0 ~ 65535이다. 실제로는 컴퓨터는 숫자만 이해할 수 있으므로 문자가 아니라 문자에 해당하는 유니코드가 저장된다. 또한 char 자료형에 대응되는 리터럴은 작은 따옴표(') 안에 하나의 문자만을 적어야 한다.

 

public class Main {
    public static void main(String[] args) throws Exception {

        char ch = 'A';
        char ch2 = 65;

        System.out.println(ch);
        System.out.println(ch2);

        int num = 76;

        System.out.println((char) num);

    }

}
A
A
L

 

 다음과 같이  문자형 변수 ch, ch2에 각각 'A', 65를 넣어도 출력되는 것은 A로 똑같다. 또한 int형 num 변수의 값을 char형으로 형변환(casting; 캐스팅)해서 출력하면 유니코드에 대응되는 문자가 출력된다. 이를 반대로 이용하면 어떤 문자의 유니코드를 알 수 있다.

 

 

 


1.3 정수형 (byte, short, int, long)

 정수형에는 모두 4개의 자료형이 있으며 각 자료형이 저장할 수 있는 정수의 범위가 다르다. 앞에서부터 1byte, 2byte, 4byte, 8byte이다. 이 중 기본 자료형(Default Data Type)은 int이다. 어떤 진법의 리터럴을 변수에 저장해도 실제로는 모두 2진수로 바뀌어서 저장되며, JVM의 피연산자 스택(Operand Stack)이 피연산자를 4byte 단위로 저장하기 때문에 4byte보다 작은 byte(1byte)나 short(2byte) 자료형으로 데이터를 저장해도 결국 연산을 수행할 때는 다시 4byte로 변환된다. 따라서 정수를 사용할 때는 일반적으로 int형을 사용하는 것이 효율적이다. 결론은 대략적으로 20억 이하의 정수를 저장할 때는 int 타입, 그 이상은 long타입을 사용하는 것이 일반적으로 바람직하며, 연산보다 저장공간을 효율적으로 다뤄야 할 때만 byte나 short 타입을 사용하면 된다.

 

public class Main {
    public static void main(String[] args) throws Exception {

        byte cash = 100;
        short moreCash = 5000;

        Object result = (Object) (cash + moreCash);

        System.out.println(result.getClass().getName());
    }

}
java.lang.Integer

 보다시피 byte타입과 short 타입의 연산의 결과는 Integer 즉 정수형으로 변환됐다.

 

 

 


1.4 실수형 (float, double)

  실수를 저장하기 위한 타입으로 float와 double 두 가지가 있다. 각각 4byte와 8byte이며 정밀도는 각각 7자리와 15자리다. 둘 다 부호(Sign), 지수(Exponent), 가수(Mantissa) 세 부분으로 값을 저장하는 부동소수점 방식이며, 정수형과 다른 점은 저장할 수 있는 값의 범위를 넘어서면 오버플로우가 발생하는 것이 아니라, 값이 무한대(infinity)가 된다. 또 실수형은 소수점을 표현해야 하므로 '얼마나 0에 가깝게 표현할 수 있는가' 또한 중요하므로 실수형으로 표현할 수 없는 아주 작은 값이 되는 언더플로우가 발생하면 변수의 값은 0이 된다.

 


2. 참조형

 위의 기본 자료형 8가지를 제외한 모든 객체는 참조형 변수가 될 수 있다.

 

// AddSomething.java

public class AddSomething {
    public AddSomething() {
        System.out.println("-- AddSomething Constructor --");
    }

    public void run() {
        System.out.println("-- run() method --");
    }
}
// Main.java

public class Main {
    public static void main(String[] args) throws Exception {
        AddSomething addSomething = new AddSomething();

        addSomething.run();
    }
}
-- AddSomething Constructor --
-- run() method --

 

 위의 두 개의 파일 AddSomething.java, Main.java가 있다. Main 클래스에서 AddSomething클래스를 호출한 것과 같이, 자바는 한 개의 패키지 안에서는 임포트없이 다른 클래스에 접근할 수 있다.

 

 Main 클래스의 변수 선언 부분을 보면 addSomething이라는 참조형 변수의 타입으로 AddSomething이라는 클래스를 지정하고, AddSomething 객체를 만들었다. 자바에서는 참조형 변수를 이런 식으로 선언한다.  그리고 결과를 보면 run() 메소드를 직접 실행하기 전에 AddSomething Constructor가 실행된 것을 알 수 있는데,  자바에서는 객체가 생성될 때(new AddSomething) 해당 클래스의 생성자(Constructor)가 호출되기 때문이다.

 

특히 문자열을 저장하는 String타입은 예외로 다음과 같이  세 가지 방식으로 호출 가능하다.

public class App {
    public static void main(String[] args) throws Exception {
        String a = new String();
        a = "김치만두";

        String b = "고기만두";
        
        String c;
        c = "갈비만두";
    }
}
반응형