변수, 상수, 리터럴

박영준·2022년 11월 7일
0

Java

목록 보기
62/111

변수

1. 정의

  • 하는 수(값)

  • 메모리(RAM)에 시간에 따라 변하는 값을 기록하기 위한 저장공간

  • 항상 메인 함수에서 시작
    (단, 클래스 이름 Main 은 달라질 수 있음)

  • final 키워드가 붙지 않음

  • 타입 맞추기
    → 정수 타입 변수에는 정수값만, 실수 타입 변수에는 실수값만 저장 가능

  • 변수의 사용 범위
    : 중괄호 { } 에서 선언된 변수는 해당 중괄호 { } 블록 내에서만 사용 가능

  • 콤마(,)를 이용해서 한꺼번에 선언 가능

2. 변수 명명 규칙

('공통 명명 규칙'과 동일)

  1. 영문자, 숫자, $, _ 로만 구성 가능

    • 첫 번째 글자
      • 문자 / $ / 언더바 (O)
      • 숫자 (X)
  2. 영어 대소문자 구분

    • firstname 과 firstName 은 다른 변수
    • 첫 문자는 영어는 소문자로.
      다른 단어가 붙을 경우, 첫 문자는 대문자로(캐멀 케이스 규칙) : maxSpeed, carBodyColor
  3. 문자 수(길이) 제한 X

  4. 예약어 X
    (예약어로 변수명을 선언하면 컴파일 에러 발생)

    참고: 클래스, 객체, 인스턴스 - 3) 클래스 선언 - (1) 작성자 식별 규칙

3. 종류

1) 정의

class Variables {
	static int cv;		// 클래스 변수
	int iv;				// 인스턴스 변수
    
    void method() {
    	int lv = 0;		// 지역 변수
    }
}

변수의 선언 위치에 따라, 변수의 종류가 결정된다.

클래스 변수 (CV)

  • 'static 변수' 라고도 함
  • 선언 방법 : 인스턴스 변수 앞에 'static'만 붙여서 선언
  • 인스턴스 변수(별도의 저장공간을 가지는)와는 달리, 모든 인스턴스가 공통된 저장공간(변수)를 공유함
    • 한 클래스에서 모든 인스턴스들이 공통된 값을 유지해야할 경우에 사용
  • 인스턴스 변수(인스턴스를 생성해야하는)와는 달리, 인스턴스 생성없이 언제라도 바로 사용 가능
  • 접근 방법 : 클래스명.클래스변수명

인스턴스 변수 (IV)

  • 클래스 영역에 선언됨
  • 인스턴스를 생성할 때 만들어짐
  • 인스턴스마다 별도의 저장공간을 가지므로, 서로 다른 값을 가질 수 있음
    • 인스턴스마다 고유한 상태를 유지해야할 경우에 사용
  • 접근 방법 : 참조변수명.인스턴스변수명

지역 변수

  • 선언 방법 : 메서드 내에 선언
    • 단, 메서드 내에서만 사용 가능!
    • 메서드의 매개변수 또한 지역변수다
    • 따라서 메서드가 종료되면 소멸됨
      • 예시 : for문, while문의 {}블럭 내에 지역변수가 선언되고, {}블럭 벗어나면 사용 불가
    • 지역변수는 사용 전에 반드시 초기화해야 한다
    • 메모리 부담 : 지역 변수 小 < 클래스 변수, 인스턴스 변수

참고: this, final, public static void main(String[] args) - 3) static

2) 예시

예시 1

Card클래스

class EX {
	System.out.println(Car.width);		// 클래스명.클래스변수명
    System.out.println(Car.width);

	Card c1 = new Card();		// 인스턴스 생성
    c1.kind = "Heart";			// 참조변수명.인스턴스변수명 -> 인스턴스 변수의 값을 변경
    c1.number = 7;
    
    Card c2 = new Card();		// 인스턴스 생성
    c2.kind = "Space";			// 참조변수명.인스턴스변수명
    c2.number = 4;
    
    c1.width = 50;				// 클래스 변수의 값을 변경 (인스턴스 생성없이)
    c1.height = 80;
    
    ...
    
}

Main클래스

class Card {
	String kind;		// 인스턴스 변수 (개별 속성)
    int number;			// 인스턴스 변수 (개별 속성)
    static int width = 100;		// 클래스 변수 (공통 속성)
    static int height = 250;	// 클래스 변수 (공통 속성)
}

예시 2

class InitTeest {
	int x;			// 인스턴스 변수 -> 기본값으로 자동 초기화됨
    int y = x;		// 인스턴스 변수 -> x값으로 초기화됨

	void method1() {
    	int i;			// 지역 변수 -> 자동적으로 초기화되지 않음
        int j = i;		// 에러 발생 -> 지역변수를 초기화하지 않고 사용했기 때문
    }
}

예시 3

class EX {
	public static void change(String str) {
    	str += "456";		// change메서드의 지역변수 -> change메서드가 종료되면, str도 메모리에서 제거된다
    }
    
    public static void main(String[] args) {
    	String str = "ABC"
        System.out.println(str);
        change(str);
        System.out.println(str);
    }
}

/* 출력 결과
ABC
ABC			// 456 이 아니다
*/

4. 분류 및 타입

참고: 필드 - 2. 필드 선언

5. 사용법

1) 기본 형태

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

2) 변수 선언

public class Main {
   public static void main(String[] args) {
   
   		변수타입 변수명;
        byte num;
        short num;
        char num;
        int num;
        long num;
        float num;
        double num;
   
   		boolean isTrue;
        
        String str;
   }
}

3) 변수 초기화

① 변수 선언과 초기화

public class VariableInitializationExample {
	public static void main(String[] args) {

		// 방법 1 : 변수 선언 후, 초기화
        int num;
        num = 30;
        
        // 방법 2 : 변수 선언 + 초기화
    	int num = 30;

    	System.out.println(num);
	}
}

② 변수의 종류에 따라

  1. 지역 변수의 초기화

    • 사용 전에 수동으로 반드시 초기화 해야 함
      • 지역 변수가 동작하는 스택 메모리는 재사용이 빈번하기 때문에, 매번 초기화 해주면 성능이 떨어집니다.
      • 그래서 그냥 해당 메모리에 있는 값으로 덮어 씌웁니다.
      • 근데 해당 주소에 어떠한 값이 있는지 모르기 때문에 Java는 개발자에게 수동으로 초기화 하라고 요구합니다.
      • C 언어에서는 이를 garbage value 라 부릅니다.(C언어와 Java의 차이를 비교하면 이해가 쉽습니다.)
  2. 멤버 변수(인스턴스 변수, 클래스 변수)의 초기화

    • 자동으로 초기화된다
      • 클래스 변수 : 클래스가 처음 로딩될 때 단 한번만 초기화
      • 인스턴스 변수 : 인스턴스가 생성될 때 마다 초기ㅌㅌ

③ 방법

  1. 명시적 초기화

    class Tv11_1 {
        boolean power = false;    	// 기본형 변수의 초기화
        int channel = 1;          	// 기본형 변수의 초기화
        Audio audi = new Audio(); 	// 참조형 변수의 초기화 -> 참조형은 객체주소 or null(기본값) 로 초기화!!
        
        ...
    }
    • 간단한 초기화 방법
    • 가장 우선적으로 고려되는 초기화 방법
  2. 초기화 블럭 (2가지 종류)

    class EX {
        static boolean power;
        int channel; 
    
        // 종류 1 : 클래스 초기화 블럭
        static 
        {
            power = false;
        }
    
        // 종류 2 : 인스턴스 초기화 블럭
        {
            channel = 1;  
        }
        ...
    }
    • 클래스 초기화 블럭

      • 클래스 변수의 초기화에 사용
      • static + 인스턴스 초기화 블럭
      • 처음 메모리에 로딩될 때, 한 번만 수행
    • 인스턴스 초기화 블럭

      • 인스턴스 변수의 초기화에 사용
      • 클래스 내에 {}블럭을 만든 후, 여기 안에 코드 작성
      • 인스턴스가 생성될 때마다 수행
  3. 생성자 초기화

    class Tv11_3 {
        // 속성 : 변수 선언
        boolean power; // 전원상태
        int channel;  // 채널
        String color; // 색깔
        long price; // 가격
    
        // 위 속성에서 필수로 초기값이 필요한 값들을 초기화 해주는 기본 생성자
        Tv11_3() {
            this.power = false;
            this.channel = 1;
        }
        ... 
    }

4) 변수 사용

public class VariableInitializationExample {
    public static void main(String[] args) {

		// 변수를 사용하지 않을 경우
        System.out.println(3 + "시간" + 5 + "분");
        System.out.println("총" + 185 + "분");
        
        
        // 변수를 사용할 경우
        int hour = 3;
        int minute = 5;
        
        System.out.println(hour + "시간" + minute + "분");

        int totalMinute = (hour*60) + minute;
        System.out.println("총" + totalMinute + "분");
    }
}

/* 출력 결과
3시간5분
총185분 */
  • 변수를 사용하지 않을 경우 : 계산이 필요할 경우, 매번 직접 숫자를 입력해줘야 한다.

  • 변수를 사용할 경우

    • 해당 숫자(값)이 대입된 변수만 가져오면, 매번 숫자를 입력하지 않아도 된다.
    • 해당 변수를 다른 출력 계산식에 사용하더라도, 잘못된 숫자를 입력하는 오류를 범하지 않게 된다.
    • 코드의 의미 파악이 용이하다.

5) 변수값 교환

public class VariableInitializationExample {

    public static void main(String[] args) {

        int x = 3;
        int y = 5;
        System.out.println("x:" + x + ", y:" + y);		// x:3, y:5

        int temp = x;		// temp:3, x: , y:5
        x = y;		// temp:3, x:5, y:
        y = temp;		// x:5, y:3, temp:
        System.out.println("x:" + x + ", y:" + y);
    }
}

/* 출력 결과
x:3, y:5
x:5, y:3 */

6) 재할당

public class Main {
    public static void main(String[] args)
    
        int number = 5;
        System.out.println(number);

        String sparta = "Hello Sparta";
        System.out.println(sparta);
    }
}
  • 지속적으로 변수의 값을 변경 가능
    → 즉, 재할당이 가능하다.
    → 재할당하면, 마지막에 할당한 값이 출력된다.

    = 는 '할당한다.' 라는 의미

6. 기본형 vs 참조형

1) 저장 관점에서 차이

  • 기본형 변수

    • 원본값이 Stack 영역에 있다.
  • 참조형 변수 (= 주소형 변수)

    • 원본값이 Heap 영역에 있다.
    • Stack 영역에는 따로 저장 해둔 원본값의 Heap 영역주소를 저장

2) 시점

  • 기본형

  • 참조형

    • 대문자
    • 클래스 생성 후에야 가능

3) 계산

Java 는 참조형 변수 간의 연산이 불가능하므로, 모두 기본형 변수가 실제 연산에서 사용된다.

4) 매개변수

(1) 기본형 매개변수

class Data6_1 {
    int x; // 기본형
    int y; // 기본형
}

class Data6_1Main {
    public static void main(String[] args) {

        Data6_1 data  = new Data6_1();
        data.x = 10;
        data.y = 20;

        System.out.println("Data6_1 클래스로 만든 data 인스턴스의 인스턴스 변수 x, y 값 확인");
        System.out.println("data 인스턴스 변수 x = " + data.x);
        System.out.println("data 인스턴스 변수 y = " + data.y);
        System.out.println();

        // changeParameter 메서드 의 매개변수에 Data 클래스의 인스턴스 변수를 입력한다.
        System.out.println("입력받은 매개변수의 값을 바꾸는 메서드 수행");
        changeParameter(data.x, data.y);
        System.out.println();

        // changeParameter(data.x, data.y); 여기서의 data.x 와 data.y 는
        // data 의 인스턴스 변수의 값 그자체가 복사되어 넘어갑니다.
        // 따라서 changeParameter 메서드에서 입력받은 매개변수의 값을 바꿔도
        // 영향을 받지 않습니다.
        System.out.println("Data6_1 클래스로 만든 data 인스턴스의 인스턴스 변수의 값이 변경되었는지 확인");
        System.out.println("changeParameter 메서드 수행 후 data 인스턴스 변수 x = " + data.x);
        System.out.println("changeParameter 메서드 수행 후 data 인스턴스 변수 y = " + data.y);
    }

    static void changeParameter(int x, int y) {
        System.out.println();
        System.out.println("changeParameter 메서드 시작");
        System.out.println("입력 받은 매개변수 x 와 y의 값 확인");
        System.out.println("입력 받은 매개변수 x = " + x);
        System.out.println("입력 받은 매개변수 y = " + y);

        System.out.println();
        System.out.println("입력 받은 매개변수 x 와 y의 값을 변경 한 후 확인");
        x = 100;
        y = 200;
        System.out.println("변경 한 후 x = " + x);
        System.out.println("변경 한 후 y = " + y);
        System.out.println("changeParameter 메서드 끝");
    }
}
  • 변수의 값을 읽기만 할 수 있다.

(2) 참조형 매개변수

class Data6_2 {
    Data6_3  data2 = new Data6_3(); // 참조형
}

class Data6_3 {
    int x; // 기본형
    int y; // 기본형
}

class Data6_2Main {
    public static void main(String[] args) {

        Data6_2 data  = new Data6_2();
        data.data2.x = 10;
        data.data2.y = 20;

        System.out.println("Data6_2 클래스로 만든 data 인스턴스의 data2인스턴스의 인스턴스 변수 값 확인");
        System.out.println("참조변수 data2의 인스턴스 변수 x = " + data.data2.x);
        System.out.println("참조변수 data2의 인스턴스 변수 y = " + data.data2.y);
        System.out.println();

        // changeParameter 메서드 의 매개변수에 Data6_2 클래스의 참조형 변수인 data2 를 입력
        System.out.println("입력받은 매개변수의 값을 바꾸는 메서드 수행");
        changeParameter(data.data2);
        System.out.println();

        // changeParameter(Data6_3 data2); 여기서 data.data2 는
        // data 인스턴스의 참조형 변수 data2의 주소값이 넘어 갑니다.
        // 따라서 changeParameter 메서드에서 입력받은 data2의 주소값을 통해
        // data2 의 인스턴스에 접근하여 인스턴스 변수를 바꾸기 때문에 영향을 받습니다.
        System.out.println("Data6_3 클래스로 만든 data 인스턴스의 참조변수 data2의 인스턴스 변수 값이 변경되었는지 확인");
        System.out.println("changeParameter 메서드 수행 후 data2의 인스턴스 변수 x = " + data.data2.x);
        System.out.println("changeParameter 메서드 수행 후 data2의 인스턴스 변수 y = " + data.data2.y);
    }

    static void changeParameter(Data6_3 data2) {
        System.out.println();
        System.out.println("changeParameter 메서드 시작");
        System.out.println("입력 받은 매개변수 data2의 인스턴스 x 와 y의 값 확인");
        System.out.println("입력 받은 매개변수 data2의 인스턴스 x = " + data2.x);
        System.out.println("입력 받은 매개변수 data2의 인스턴스 y = " + data2.y);

        System.out.println();
        System.out.println("입력 받은 매개변수 data2의 인스턴스 x 와 y의 값을 변경 한 후 확인");
        data2.x = 100;
        data2.y = 200;
        System.out.println("변경 한 후 data2의 인스턴스 x = " + data2.x);
        System.out.println("변경 한 후 data2의 인스턴스 y = " + data2.y);
        System.out.println("changeParameter 메서드 끝");
    }
}
  • 변수의 값을 읽고 변경할 수 있다.

5) 참조변수의 형변환

참고: 타입 및 형변환

  • Car 부모 클래스, Engine 자식 클래스, Tire 자식 클래스 가 있다고 가정할 때
Engine e = new Engine();

Car c = (Car)e;				// 자식 -> 부모 형변환 ((Car) 생략 가능 O)
Engine e2 = (Engine)c;		// 부모 -> 자식 형변환 ((Engine) 생략 X)
Tire t = (Tire)e;			// 에러 : 자식 클래스 간에는 상속관계가 아니기 때문
  • 서로 상속관계에 있는 클래스 사이에서만 참조변수의 형변환이 가능

    • 자식 타입의 참조변수 -> 부모 타입의 참조변수로
    • 부모 타입의 참조변수 -> 자식 타입의 참조변수로
  • 단, (기본형 형변환과는 달리) 변수에 저장된 주소값이 변환되는 것은 X

    • 그저 참조변수를 다른 종류로 바꾸는 것일 뿐.
      • 이유? 사용 가능한 멤버 개수를 조절하기 위함

상수

1. 정의

  • 변하지 않는 값
    → 항 그대로인 수

  • 변하지 않는 저장공간

  • 중간에 값이 변할 수 없으며, 초기값을 끝까지 사용해야 함
    → 즉, 재할당이 불가능

  • final 키워드를 붙여서 선언

  • 숫자에 의미있는 이름을 붙여, 코드 자체의 가독성을 늘리기 위해 상수를 사용

    참고: this, final, public static void main(String[] args) - 2. final

2. 상수 명명 규칙

  1. 모든 문자는 영문자 대문자 or 숫자만 사용

  2. 단어와 단어 사이는 언더바(_)를 사용

    (나머지는 변수와 동일)

3. 사용법

(1) 상수 선언

public class Main {
    public static void main(String[] args) {
    
 		// 방법 1 : 상수 선언 후, 초기화
 		final int NUM;
 		NUM = 100;
  
 		// 방법 2 : 상수 선언 + 초기화
 		final int NUM = 100; 
 
    }
}    
  • final 변수타입 변수이름;

(2)

public class Main {
    public static void main(String[] args) {
    
        int number = 5;
        System.out.println(number);

        String sparta = "Hello Sparta";
        System.out.println(sparta);

        final int finalNumber = 1;
        System.out.println(finalNumber);
        
        sparta = "Good Bye Sparta";
        System.out.println(sparta);
    }
}

리터럴

1. 정의

  • 그 자체로 값

  • 상수와 같은 의미이나,
    Java에서 상수를 '한 번만 값이 저장 가능한 변수' 라는 의미로 사용하기 때문에 이를 구별하기 위해 사용하는 용어

2. 종류

1) 문자 리터럴

char ch = 'J';			// O
char ch = 'Java';		// X
char ch = ``;			// X
char ch = ` `;			// O
  • char 타입

  • 하나의 문자만 저장 가능

  • '' 안에 반드시 하나의 문자가 있어야 함

2) 문자열 리터럴

String naem = "Java";		// O
String str = "";			// O
  • string 타입

  • 문자 여러개(문자열) 저장 가능

  • "" 안에 문자가 없어도 됨

    • '빈 문자열' 이라고 함

변수 vs 상수 vs 리터럴

class Variable2_2 {
    public static void main(String[] args) {
        int score = 100;
        final int finalScore = 1000;
    }
}
  • score : 변수 → 값 하나를 저장하기 위한 공간

  • finalScore : 상수 → 값을 한 번만 저장할 수 있는 공간

  • 100, 1000 : 리터럴 → 값 그 자체


참고: [자바JAVA] 변수와 상수 (선언하기 , 초기화하기, 규칙)

profile
개발자로 거듭나기!

0개의 댓글