[Java] 2. Java와 변수 그리고 String

Kyunghwan Ko·2022년 9월 20일
0

Java

목록 보기
3/14

01. introduce

환경변수

  • 시스템 부팅 시, OS가 환경변수 편집을 읽어들인다. 환경변수에 설정되어 있는 경로 → bin 폴더 → javac.exe가 실행된다.
  • cmd에 java --version 을 하게 되면 java.exe가 실행된다.
  • 환경변수 등록 목적은 언제 어디서든 실행시켜주기 위해서이다.

HelloWorld.java 생성

public class HalloWorld {

	public static void main(String[] args) {
		System.out.println("Hello world");
	}
}

02. 변수와 참조

변수

1, 인스턴스 변수: 클래스 내부에 있는 변수, 인스턴스 생성해야지만 사용가능o
ex. private int num;
2. static 변수: 클래스 올라갈 때 메모리에 같이 올라가서 인스턴스 생성없이 사용가능o
ex. static private int num;
3. 지역변수: 함수안에서 선언된 변수
4. 전역변수:
- 전역변수(객체변수): 같은 클래스안에서 어디든지 호출 가능o
- 전역변수(클래스변수): 다른 클래스에서 어디든지 호출 가능o

 class Main{
 	int global_int; // 전역변수(객체변수)
     static int global_static_int; //전역변수(클래스변수)
     public double getArea(){
     	private int radius; // 지역변수 (함수 끝나면 메모리에서 사라짐)
         ...
     }
 }

변수 선언

  • 메모리 할당(Assign)을 의미

변수 선언 후의 메모리

int num;
num = 256;
  • 메모리에 주소가 존재
  • 메모리 관리 주체 : OS
  • JVM(Java Virtual Machine) : OS에 메모리 요청하는 역할

변수 명명규칙(Convention)

int appleNum = 10;

합성어를 사용 시, 뒤에 오는 단어 첫글자를 대문자로 사용한다. 해당 표기법을 Camel Case 라고 한다.

  1. 대소문자가 구분되며 길이에 제한이 없다.
  2. 예약어를 사용해서는 안 된다.
  • 예약어 종류

    abstract, assert, boolean, break, byte, case, catch, char, class, const, continue, default, do, double, else, enum, extends, false, final, finally, float, for, if, goto, implements, import, instanceof, int, interface, long, native, new, null, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, true, try, void, volatile, while

  1. 숫자로 시작해서는 안 된다.
  2. 특수문자는 _ 와 $만을 허용한다.

변수 초기화

int num = 100;

변수값에 처음으로 할당하는 것을 변수 초기화(initialization)라고 한다.

변수 예제

자바에서 = 는 대입(Assign)을 의미한다.

int num1;
num1 = 10;

		
int num2 = 20;
int num3 = num1 + num2; // 10 + 20
System.out.println(num1 + " + " + num2 + " = " + num3);

해당 코드의 변수 메모리 할당 표현

  • int는 4Byte 만큼의 메모리 공간이 필요하기 때문에 위와 같이 각 iut변수마다 4씩 차지하는 것을 볼 수 있고

  • OS가 메모리에 변수를 올리기 때문에 물리적 순서는 위와 같지 않을 수 있다.

03. 데이터타입

JAVA 자료형 크기

  • 1byte = 8bit
자료형범위크기(byte)기본값
booleantrue, false1false
char0 ~ 65,535 (유니코드 문자)2'\u0000'
byte-128 ~ 12710
short-32,768 ~ 32,76720
int-2,147,483,648 ~ 2,147,483,64740
long-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,80780L
float±1.4E-45 ~ 3.4E3840.0f
double±4.9E-324 ~ 1.8E30880.0 또는 0.0d

컴퓨터에서 실수연산 시 오차가 생기는 이유

double num = 0.1;

for(int i = 0; i < 1000; i++) {
	num += 0.1;
}
		
System.out.println(num);

해당 코드를 실행시켰을 때, 100.09999999999859 해당 결과가 나온다. 이러한 오차가 나는 이유는 실수를 이진수로 표현해서 나오는 오차이다.

문자와 문자열

// 문자
char ch1 = '하';
char ch2 = '이';
		
// 문자열
String str1 = "하이";
char ch1 = '가';
'가' 를 메모리에 담기 위해 숫자로 Encoding
숫자는 문자로 decoding
char ch1 = '헐';
char ch2 = '확';
char ch3 = 54736; // 문자 '헐'의 유니코드 값
char ch4 = 54869; // 문자 '확'의 유니코드 값
char ch5 = 0xD5D0;
char ch6 = 0xD655;
		
System.out.println(ch2 + " " + ch2);
System.out.println(ch3 + " " + ch4);
System.out.println(ch5 + " " + ch6);

String

Java에서 문자열을 생성하는 과정은 2가지 방법이 있다.
1. 문자열 리터럴(Literal)을 사용

public class Main {
  public static void main(String[] args) {
    String strLiteral1 = "TEST";
    String strLiteral3 = "TEST";
    String strLiteral2 = "Java";
  }
}

2. new String()을 사용

public class Main {
  public static void main(String[] args) {
    String strObject1 = new String("TEST");
    String strObject2 = new String("TEST");
    String strObject3 = new String("Java");
  }
}

리터럴(Literal)과 new String()의 차이점

문자열 리터럴(Literal)의 생성 과정

public class Main {
  public static void main(String[] args) {
    String strLiteral1 = "TEST"; // 1번 과정
    String strLiteral2 = "TEST"; // 2번 과정
    String strLiteral3 = "Java"; // 3번 과정
  }
}

생성 과정

  1. String Pool에 "TEST"가 생성됩니다.
  2. JVM이 String Pool에 "TEST"가 이미 존재하므로 strLiteral2은 1번 과정에서 생성된 "TEST"를 참조합니다.
  3. String Pool에 "Java"가 생성됩니다.

new String()의 생성 과정

public class Main {
  public static void main(String[] args) {
    String strObject1 = new String("TEST"); // 1번 과정
    String strObject2 = new String("Java"); // 2번 과정
    String strObject3 = new String("TEST"); // 3번 과정
  }
}

생성 과정

1. Java Heap에 "TEST"가 생성됩니다.
2. Java Heap에 "TEST"가 생성됩니다.
3. Java Heap에 "Java"가 생성됩니다.

문자열 리터럴(Literal)과 다르게 new String()으로 생성된 문자열은 Heap 영역에 생성이 된다. 그리고 동일한 문자열이라도 기존의 문자열을 참조하지 않고 새로 생성된다.

String Pool은 무엇인가?

String Pool은 Heap의 저장 영역이다. JVM은 과도한 String 개체의 수를 줄이고자 문자열 리터럴이 생성될 때마다 String Pool을 체크한다. 문자열이 이미 String Pool에 존재하는 경우에는 인스턴스에 대한 참조가 반환된다. 존재하지 않으면 새로운 인스턴스가 String Pool에 생성이 된다.

일반적으로 리터럴(Literal)을 사용하는 것이 읽기가 더 쉬우며, 컴파일러가 코드를 효율적으로 최적화한다.

== vs equals()

public class Main {
  public static void main(String[] args) {
    String strLiteral1 = "TEST";
    String strLiteral2 = "TEST";
    String strLiteral3 = "Java";
    
    String strObject1 = new String("TEST");
    String strObject2 = new String("TEST");
    String strObject3 = new String("Java");
    
    System.out.println("strLiteral1 == strLiteral2 : " + (strLiteral1 == strLiteral2));
    System.out.println("strObject1 == strObject2   : " + (strObject1 == strObject2));
    System.out.println("strLiteral1 == strObject1  : " + (strLiteral1 == strObject1) + "\n");
    
    System.out.println("strLiteral1.equals(strLiteral2) : " + (strLiteral1.equals(strLiteral2)));
    System.out.println("strObject1.equals(strObject2)   : " + (strObject1.equals(strObject2)));
    System.out.println("strLiteral1.equals(strObject1)  : " + (strLiteral1.equals(strObject1)));
  }
}

실행결과는 다음과 같다.

== 연산자

동일한 메모리 공간인지 비교를 하는 연산자(operator)

equals()

객체의 내용을 비교하는 메소드

결과 설명

위 코드의 문자열 리터럴(Literal)과 new String() 객체의 Heap 메모리 구조는 아래 그림과 같다.

업로드중..

strLiteral1 == strLiteral2
strLiteral1과 strLiter2는 동일한 공간을 참조하고 있다.
즉, 참조하는 주소가 같으므로 true이다.

strObject1 == strObject2
strObject1과 strObject2는 다른 공간을 참조하고 있다.
즉, 참조하는 주소가 다르므로 false이다.

strLiteral1 == strObject1
strLiteral1과 strObject2는 다른 공간을 참조하고 있다.
strLiteral1은 String Pool 내부의 공간을 참조힌다.
strObject2는 String Pool 외부의 공간을 참조한다.
즉, 참조하는 주소가 다르므로 false이다.

.equals()
변수가 참조하는 공간에 있는 값의 일치여부를 판단하기 때문에 true이다.

boolean

int num1 = 10;
int num2 = 20;
		
System.out.println(num1 < num2);

결과값 true 반환

null

1, 가리키는 값이 없다
2. GC(Garbage Collector)로 하여금 해당 메모리를 회수 해도 좋다는 의미

Tip

출력시 int타입으로 자동형변환 발생

short num1 = 11;
short num2 = 22;

sout(num1 + num2); // 33 -> int타입(int이하의 타입은 default로 int로 자동형변환된다)

// short로 타입을 유지하고 싶은 경우
short num3 = (short) (num1 + num2);
profile
부족한 부분을 인지하는 것부터가 배움의 시작이다.

0개의 댓글