변수

cutiepazzipozzi·2023년 4월 11일
2

지식스택

목록 보기
17/35
post-thumbnail

기본형과 참조형에 대해 간략히 정리해 본 글. 겹치는 내용이 많을것이다

🤓변수

= 단 하나의 값만을 저장할 수 있는 메모리 상의 공간

int a = 5;
int b = 5;

System.out.println(a == b); 
(X) System.out.println(a.equals(b));

위의 출력이 true로 나올 수 있는 이유는 a와 b가 가리키고 있는 주솟값이 같기 때문에! (같은 값 5를 저장하는 메모리 상의 공간을 가리키고 있기 때문에)

** equals는 객체끼리 두 값이 리터럴 하게 같은지 확인해주는 함수이기 때문에 기본형에선 쓸 수 없음!

보통은

int a = 10; 

int b;
b = 5;

이렇게 두가지의 경우로 변수의 선언과 함께 초기화 한다.

** 지역변수는 무조건 초기화를 해야 하지만, 클래스변수인스턴스변수는 초기화를 생략할 수 있다.
(왜냐면 각 타입의 기본값으로 초기화 할 수 있기 때문
ex. int[] arr = new int[10] => 값이 0으로 초기화됨)

내가 기억하고 싶은 변수 명명규칙

  • 클래스 이름은 영문자로 되도록이면 하자!
    = 유니코드를 인식하지 못하는 운영체계도 있기 때문에 ASCII 코드인 영문자로 하는게 더 안전!

👍변수의 타입

코딩 호구마가 가볍게 정리해본 자바의 타입들

기본적인 설명은 위의 포스팅을 참조하면 된다.

  • 변수의 타입을 알아야 하는 이유: 타입에 따른 값의 종류와 범위가 달라지는데, 이를 변수 선언시 저장할 값을 고려해서 넣어줘야 효율적이기 때문!

  • 참조변수

    Student s1 = null;
    Student s2 = new Student();
    //아래의 경우처럼 참조변수는 null or 주소값을 갖는다.
    //여기서 객체를 생성하는 연산자 new가 사용됨으로써 새로운 객체의 주소를 생성한다.
    //대입연산자 '='에 의해서 s2에 주소값이 저장됨

=> 참조형 변수는 기본형 변수들과 다르게 어떤 객체의 주소값을 저장할 것인가에 따라 구분되기 때문에, 자료형 대신 타입이라는 용어를 사용한다!
(자료형 ( 타입 -> 따라서 굳이 구분할 필요는 없긴 함,,)

기본형

위에서 정리한 것 처럼 총 8개의 자료형이 있다.

  • 논리형 - boolean
  • 문자형 - char,
  • 정수형 - int, long, byte, short
  • 실수형 - float, double
    (두꺼운 글씨가 기본 자료형!)


위의 그림은 기본형의 크기인데 이 크기에 따라 저장 가능한 값의 범위가 달라진다. 이때 정수형 4가지는 음의 값도 갖는다.
(ex. char -> 2byte -> 16bit -> 0~2^16-1까지)

특징

  • 논리형을 제외한 나머지 7개의 자료형은 서로 변환이 가능하다.
  • 모든 데이터는 숫자로 저장된다.

논리형(boolean)

  • 논리형은 true, false 2가지 값만 표현하면 되므로 1bit로도 충분하지만 데이터를 표현하기 위한 가장 작은 단위가 1byte이므로 1byte로 크기를 잡았다.

문자형(char)

  • char은 문자를 내부적으로 정수 코드로 저장한다.

    char first = 'A';
    char first2 = '\u0041';
    //이렇게 두개가 같은 말, 아래는 A를 16진수로 바꿨을 때 41
    
    int code = 65;
    char c = (char) code;
    System.out.println(c) // casting(형변환)되어 A가 출력됨!

    (유니코드(국제적인 코드 규약)를 사용하므로 2byte)

    **여기서 유니코드는 한글, 한자, 일어등의 문자가 1byte로 표현이 불가하기 때문에 탄생하여 2byte로 문자를 표현함

  • 이때 char형 변수는 한 문자밖에 저장이 안되기 때문에 String클래스를 사용해서 여러 문자를 저장한다.

  • 기본형, 참조형 구분 없이 문자열과 덧셈연산을 수행하면 그 결과는 문자열!

//example
String a = 7+7+""; //출력 14
String b = 7+""; //출력 7

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

  • 순서대로 2배씩 크기가 증가!
  • JVM의 피연산자 스택이 피연산자를 4byte 단위로 저장 하기 때문에 크기가 작은(byte, short) 값을 계산할 때는 int로 변환해 연산하는 것이 효율적이다!

*** 피연산자: 연산의 대상이 되는 값

**** JVM의 스택 영역(push, pop만 이뤄짐)에서 스택은 하나의 메서드가 실행될 때마다 스택 프레임이 생성되는데, 스택 프레임은 지역 변수 배열, 피연산자 스택, 실행 중인 메서드가 속한 클래스의 런타임 상수 풀에 대한 참조를 갖는다.

런타임 상수 풀 (내가 몰라서 짧게 정리하는)

풀(pool) = 필요할 때마다 객체를 생성하고 파괴하는 대신, 사용 준비된 상태로 초기화된 개체 집합
런타임 상수 풀 = constant pool 테이블에 있는 class나 interface별 런타임 표현 (JVM의 static 영역에서 생성)

아래는 런타임 상수 풀이 갖는 상수

  • 컴파일 타임에 알려진 숫자 리터럴
  • 런타임에 확인(resolve)되어야 하는 메서드

*** 여기서 피연산자 스택메서드의 실제 작업 공간으로 컴파일 시에 그 크기가 결정된다 (어떤 변수가 들어올지 모르니까).

  • 롱타입의 리터럴에는 접미사 l을 붙여줘야 한다

** 리터럴 = 그 자체로 데이터 (ex. "A", 'a', 1)
(상수와 비슷한 의미로 받아들여질 수 있지만, 상수는 한번 저장되면 변경할 수 없는 저장공간이기 때문에 다르다!!)

  • 저장할 수 있는 값의 범위를 넘어서면(=오버플로우), 최솟값부터 다시 반복된다.
    그러나 초기화 시 변수의 범위를 넘어가는 값으로 선언하면 오류가 발생한다!

실수형(float, double)

  • 크기는 int와 long과 같지만 표현 방식이 다르기 때문에 더 큰 범위의 값을 표현할 수 있다!
  • 실수는 부동 소수점(+- a*10^b) 방식으로 표현됨
//차례대로 부호+지수+가수
float = 1+8+23 = 32bit = 4byte
double = 1+11+52 = 64bit = 8byte
  • 또한 실수형에서는 double이 기본 자료형이므로 float를 사용할 때에는 접미사 f(혹은 F)를 꼭 붙여줘야 한다.
    ex. float num = 0.1f
    (** long, float 리터럴에는 꼭 접미사를 붙여줘야 함)

형변환(Casting)

호구마가 정리해본 캐스팅
(다만 이 포스팅은 중점적으로 클래스 사이(상속 관계)에서의 캐스팅을 많이 다루고 있음)

형변환이 필요한 이유

보통은 같은 타입의 피연산자끼리 연산이 이뤄지나, 부득이 하게 다른 타입의 피연산자가 연산을 해야할 때 형변환이 일어나야 하기 때문에 사용한다.
** 그러나 기본형은 기본형끼리, 참조형은 참조형끼리만 형변환이 가능하다. (현재는 오토박싱 기능이 생겨 Object나 Wrapper 클래스를 활용해 기본형이 참조형으로 형변환이 가능해짐)

  • 형변환이 이뤄진다고 하여 본래의 피연산자 값이 변하진 않는다.

ex. Wrapper 클래스
Integer b = 1; int a = b.intValue()

ex. 형변환 예시
int score = (int) 95.4 // 95점

  • 서로 다른 타입 변수의 연산은 형변환을 해줘야 하지만, 작은 범위 타입 -> 큰 범위 타입으로의 형변환은 생략할 수 있다.
int a = 1;
long b = a;

int c = 1;
byte d = (byte) c; //요런식으로 캐스트 연산자를 꼭 써주어야 함

연습문제 풀이

2-3. 리터럴, 변수, 상수, 키워드

int i = 100;
long l = 100L;
final float PI = 3.14f;
  • 리터럴: 100, 100L, 3.14f
  • 변수: i, l
    변수 = 단 하나의 값을 저장할 수 있는 공간
  • 상수: PI
    final -> 수정이 불가능한 값 -> 상수(선언 이후 수정 불가)
  • 키워드: int, long, float, final
    키워드 = 예약어 = 의미가 약속되어 있는 단어

2-5. 출력결과를 적으세요.

System.out.println('A'+'B') // 65+66
System.out.println('1'+2) // 49+2
System.out.println('1'+'2') //49+50
System.out.println(true+null) //오류(boolean형은 연산 불가)

2-6. 키워드가 아닌 것을 모두 고르세요.

위에서 설명한 것처럼 키워드는 의미가 약속되어 있어야 하므로
if 제외한 True, Null, Class, System 모두 아님
** True가 아니라 true였다면 키워드

2-7. 변수의 이름으로 사용할 수 있는 것을 고르세요.

a. $ystem
기호 $, _는 특이하게 허용됨
b. $MAX_NUM

2-11. 변수를 잘못 초기화 한 것?

a. byte b = 256
byte의 범위는 -127~128임..
b. char c = ''
char은 무조건 글자가 있는 상태로 초기화 돼야 함

2-12. main메서드의 선언부로 알맞은 것은?

c. public static void main(String[] arv)
e. static public void main(String[] args)
=> 인자 메서드의 이름은 아무거나 써도 되며,
static과 public은 순서를 바꿔두 됨!

** 메서드 이름이 main인 이유도 JVM(안에 명시된 메서드 이름이 main임), void인 이유도 JVM(아무것도 리턴하지 않기 위함)

2-13. 타입과 기본값이 잘못 연결된 것?

f. String - ""
String도 참조형이기 때문에 기본값은 null

참조

자바의 정석, 2nd Edition
https://velog.io/@kwak0568/JVM%EC%9D%98-%EC%9D%B4%ED%95%B4
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.5

profile
노션에서 자라는 중 (●'◡'●)

0개의 댓글