728x90

자바는 크게 기본타입 참조타입으로 구분된다.

1. 기본타입: 정수타입, 실수타입, 논리타입

  • 정수타입: byte, char, short, int, long
  • 실수타입: float, double
  • 논리타입:boolean

2.참조타입: 배열타입, 열거타입, 클래스, 인터페이스

 

기본타입으로 선언된 변수와 참조타입으로 선언된 변수의 차이점은 저장되는 값이다.

기본타입은 실제 값을 변수안에 저장한다.

참조타입은 메모리의 번지를 변수안에 저장을 하고, 번지를 통해 객체를 참조한다.

 

//기본타입변수
int age = 25;
double height=169;

int 타입 변수인 age와 double 타입 변수인 height는 직접값을 저장하고 있다.

 

//참조타입변수
String name= "kitty";
String hobby = "독서";

String 클래스 변수인 name, hobby는 힙 영역의 String 객체 번지 값을 가지고 있다.

따라서, 번지를 통해 객체를 참조하기 때문에 String 클래스 변수를 참조 타입 변수라고 한다.

 

메모리 사용영역

-메소드 영역: 정적 필드/상수, 메소드 코드, 생성자 코드 등을 분류해서 저장한다.

-힙 영역 : 객체와 배열이 생성되는 영역으로 여기에서 생성되는 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조한다.

-스택 영역 : 기본 타입 변수와 참조 타입 변수가 추가(push)되거나, 제거(pop)되는 영역이다.

char v1 = 'A';     					--1️⃣

if(v1=='A'){						--2️⃣(if문 전체)
	int v2=100;
    double v3=5.5; 
}	

boolean v4 = true;  					 --3️⃣

 

1️⃣번 실행- 스택영역

v1 A

 

2️⃣번 실행-스택영역

v3 5.5
v2 100
v1 A

 

3️⃣번 실행-스택영역

v4 true
v1 A

 

여기서 기본 타입 변수는 스택 영역에 직접 값을 가지고 있지만, 참조 타입 변수는 스택 영역에 힙 영역의 객체 주소를 가지고 있다.

 

배열변수인 scores는 스택영역에 생성되지만, 실제 100, 90, 80을 갖는 배열은 힙영역에 생성이 된다. 

int [] scores = {100, 90, 80};

따라서, 배열 변수 scores에는 배열의 힙 영역의 주소가 저장이 된다.

스택 영역

scores 힙번지

⬇️

힙 영역

scores 힙 번지

100 90 80



참조 타입 변수들 간의 ==, !=은 동일한 객체를 참조하는지, 아니면 다른 객체를 참조하는지에 대해서 구분할 때 사용을 한다.

여기서 n1은 힙영역에 객체 1을 참조하고, n2, n3는 힙영역에 객체2를 참조한다고 가정한다.

n1 == n2 //답 : false
n2 == n3 //답 : true
n2 != n3 //답 : false
n1 != n2 //답 : true

 

참조 타입 변수는 힙 영역의 객체를 참조하지 않는닫는 뜻으로 널(null)값을 가질 수 있다. null값도 초기값으로 사용할 수 있기 떄문에 null로 초기화된 참조 변수는 스택 영역에 생성된다.

만약, n1은 힙 영역에 객체 1을 참조하고, n2는 null이라면

n1 == null //결과 :false
n1 != null //결과 :true
n2 == null //결과 :true
n2 != null //결과 :false

 

NullPointerException

참조변수가 null을 가지고 있을 경우에는, 참조 변수각 없으므로 변수를 통해 객체를 사용할 수 없다. 만약 null 상태에서 있지도 않은 객체의 데이터(필드)나 메소드를 사용하는 코드를 실행하면 NullPointerException이 발생한다.

int [] name = null;
name[0] = 10; --> NullPointerException이 발생함.

위의 name은 배열 변수이므로 참조변수이다. 그래서 null로 초기화가 가능하다. 하지만, 이 상태에서 name[0]에 10을 저장하려고 하면 NullPointerException이 발생하게 된다. 왜냐하면 name 변수가 참조하는 배열 객체가 없기 때문이다.

 

String str = null;
System.out.println(str.length()); //NullPointerException발생

String 클래스 이므로 참조 타입이다. 따라서, str 변수도 null로 초기화가 가능하다.여기서 String 객체의 length()라는 메소드를 호출하면 NullPointerException이 발생한다. 왜냐하면, str변수가 참조하는 String 객체가 없기 때문이다.

 

String 타입

자바는 문자열 리터럴이 동일하다면, String 객체를 공유하도록 되어 있다. 

String name1 = "kitty";
String name2 = "kitty";

스택영역

name1  
name2  

⬇️참조(힙영역이 같은 객체를 참조하게 됨)

힙영역

kitty

 

new 연산자 : 직접 String 객체를 생성할 수 있다. 힙 영역에 새로운 객체를 만들 때 사용하는 연산자로 객체 생성 연산자라고 한다.

String name1 = new String("kitty");
String name2 = new String("kitty");

스택영역

name1  
name2  

⬇️참조(힙영역이 서로 다른 String 객체를 참조하게 됨)

힙영역

kitty

 

kitty

 

String name1 = "kitty";
String name2 = "kitty";
String name3 = new String("kitty");

name1 == name2 : true

name1 == name3 : false 서로 다른 객체를 참조하기 때문에

만약, 동일한 String 객체이건 다른 String 객체이건 상관없이 내부 문자열을 비교하고 싶을 때에는 String 객체의 equals()메소드를 사용해야 한다.

equals() 메소드는 원본 문자열과 매개 값으로 주어진 비교 문자열이 동일한지 비교한 후 true 또는 false를 리턴한다.

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;

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

        String name1 = "kitty";
        String name2 = "kitty";

        if(name1==name2){
            System.out.println("true");
        }else{
            System.out.println("false");
        }

        if(name1.equals(name2)) {
            System.out.println("name1과 name2의 문자열이 같음");
        }

        String name3 = new String("kitty");
        String name4 = new String("kitty");

        if(name3==name4){
            System.out.println("true");
        }else{
            System.out.println("false");
        }

        if(name3.equals(name4)){
            System.out.println("name3과 name4의 문자열이 같음");
        }


    }
}

결과값

true
name1과 name2의 문자열이 같음
false
name3과 name4의 문자열이 같음
728x90