ch05.classPart.Student@1ddc4ec2
의 주소값은 실제 물리적인 주소값은 아니고Student student = new Student();
System.out.println(student);
문자열(String) - 한번 만든 문자열은 변하지 않는다. (Immutable) 그래서 새로운 문자열을 만들어서 값을 넣어 주는 것과 같다.
클래스는 문자열과 달리 mutable 변할 수 있다.
참조형 객체이기 때문에 new일때만 새로운 객체를 생성하고, 이렇게 하면 같은 객체를 가리킨다.
이처럼 carThree 에 carOne을 넣었을 때 Three에서 속성 값을 변경시켰을 때 one의 속성값도 변경됨.
Car carThree = carOne;
System.out.println(carThree.speed); //carThree.speed = 5;
System.out.println(carThree.speed);// 5
System.out.println(carOne.speed);// 5
변수가 메모리에 생성될 때는 초기화가 이루어지는 시점인데,
초기화가 되는 시점은 클래스나 메소드에서 초기화 값을 준다고 해도 메모리에 생성이 되는게 아니다.
변수를 선언하는 것은 메모리를 자료형의 크기만큼 쓰겠다라고 하는 것이다.(메모리에 공간 확보)
변수 초기화는 메모리에 실제 값을 할당 하는 것이다.
메인 메소드안에 있는 변수들은 실행될 때 메모리에 생성됨.
정적 변수 - 클래스가 생성이 될 때 메모리에 할당이 된다.
클래스 영역(class area, method area, code area, static area) 클래스의 공통된 부분이 들어감 어떤 필드가 있는지 어떤 타입을 갖는다던지
어떤 메소드가 있고 어떤동작을 하는 코드라던지. 프로그램이 돌아가면 계속 존재함.
스택 영역 메소드콜이 이뤄질때 메소드에 의해 이뤄지는 임시적인 영역
힙 영역 new키워드로 발생함.
클래스와 객체의 메모리 구조 예제
public class MemoryStructure { // 클래스 영역
int x, y;
// 힙 영역 객체에 속하기 때문에 객체를 콜할 때는 힙 영역에 들어감. 객체에 속하는 속성들이므로.
// 클래스가 아니기 때문에 값 자체가 담긴다.(32비트 값을 잡아서 쓰여져있음)
String string = "String!!";
// 힙영역, 상수풀에도 생성, 애는 상수풀에 생성됨. 클래스를 만드는 클래스는 힙영역에있고 내용은 상수풀에 들어감.
public void method(int value){ // 클래스 영역에 만들어 짐 (메소드의 정의)
// int value = > 스택 영역
char c = 'w'; // 스택 영역
}
// 대부분의 주소값은 64비트 운영체제가 대부분 64비트이기때문에 거기에 맞춰지는 것.
}
class, method 같은 것들은 클래스 영역에 만들어지고,
method 안에 있는 값들은 스택영역에 만들어졌다가 method의 생명주기가 끝나면 사라짐.
class 안에 변수들은 힙영역에 생성이 되는데, 정수, 실수형 변수는 constant pool 안에 정의 되어있는 값들을 가져와서 사용하는 것이고,
String은 정의할 때 힙 영역에 값이 생성됨.
처음에 young메모리(nursery)에 생성되었다가 오랫동안 사용하면 올드메모리로 옮겨짐.
new로 생성했을 때 기본적으로 young 메모리에 들어간다.
@org.junit.Test
public void testStringEquality (){
final String literal = "Hello";
final String object = new String("Hello");
Assert.assertTrue(literal.equals(object));
Assert.assertFalse(literal == object);
}
위에서 String의 equals은 true, ==는 false가 나오는 경우를 볼 수 있는데,
equals는 문자열
을 비교하고, ==는 객체의 주소값
을 비교하기 때문이다.
@org.junit.Test
public void testStringIntern(){
final String literal = "Hello";
final String object = new String("Hello");
final String intern = literal.intern();
Assert.assertTrue(literal.equals(object));
Assert.assertFalse(literal == object);
Assert.assertTrue(literal.equals(intern));
Assert.assertTrue(literal == intern);
}
위의 코드를 보면 intern()메서드를 호출한 결과값을 intern 변수에 할당되는 것을 볼 수 있다.
그 후 literal과 object의 동일성(==)과 동등성(equals)를 비교해보면 둘다 true값이 나와 테스트에 성공하게 된다.
리터럴로 "Hello"라는 문자열이 string constant pool에 저장되었고,
inter() 메서드를 호출하면서 string constant pool에서 Hello라는 문자열을 검색하고
이미 존재하기 때문에 "Hello" 의 동일한 주소값을 반환하게 되어 true가 나오게 된다.