기본형과 참조형
- 기본형(Primitive Type): int , long , double , boolean 처럼 변수에 사용할 값을 직접 넣을 수 있는 데이 터 타입을 기본형이라 한다.
- 참조형(Reference Type): Student student1, int [ ] students와 같이 데이터에 접근하기 위한 참조(주소)를 저장하는 데이터 타입을 참조형이라 한다. 참조형은 객체 또는 배열에 사용된다.
기본형 vs 참조형 - 기본
- 기본형: 숫자 10,20과 같이 실제 사용하는 값을 변수에 담을 수 있다. 그래서 해당 값을 바로 사용할 수 있다.
- 참조형: 실제값을 담는게 아니라, 실제 객체의 위치(주소,참조)를 저장한다.
- 객체는 .(dot,점)을 통해서 메모리 상에 생성된 객체를 찾아가야 사용할 수 있다.
- 배열은 [ ] 를 통해서 메모리 상에 생성된 배열을 찾아가야 사용할 수 있다.
기본형 vs 참조형 - 계산
- 기본형은 들어있는 값을 그대로 계산에 사용 가능
- 참조형은 들어있는 참조값을 그대로 사용할 수 없다. 참조값은 계산에 사용할 수 없다 (.을 통해 접근한 경우 연산가능)
기본형 vs 참조형 - 변수대입
자바는 항상 변수의 값을 복사해서 대입한다.
참조형의 경우 실제 사용하는 객체가 아니라 객체의 참조값만 복사된다.
(예를들어 실제 건물이 복사되는게 아니라 건물의 위치인 주소만 복사되는것이다. 따라서 같은 건물을 찾아갈 수 있는 방법이 하나 늘어날 뿐이다.)
package ref;
public class VarChange2 {
public static void main(String[] args) {
Data dataA = new Data();
dataA.value = 10;
Data dataB = dataA;
System.out.println("dataA 참조값=" + dataA);
System.out.println("dataB 참조값=" + dataB);
System.out.println("dataA.value = " + dataA.value);
System.out.println("dataB.value = " + dataB.value);
//dataA 변경
dataA.value = 20;
System.out.println("변경 dataA.value = 20");
System.out.println("dataA.value = " + dataA.value);
System.out.println("dataB.value = " + dataB.value);
//dataB 변경
dataB.value = 30;
System.out.println("변경 dataB.value = 30");
System.out.println("dataA.value = " + dataA.value);
System.out.println("dataB.value = " + dataB.value);
}
}
```
실행 결과 ```
dataA 참조값=ref.Data@x001
dataB 참조값=ref.Data@x001
dataA.value = 10
dataB.value = 10
변경 dataA.value = 20
dataA.value = 20
dataB.value = 20
변경 dataB.value = 30
dataA.value = 30
dataB.value = 30
해당코드에서 dataB = dataA 대입같은 경우 참조값을 복사해서 변수 dataB에 대입했다.
그래서 둘다 똑같은 x001Data 인스턴스를 가리킨다.
dataA.value = 20을 실행하면 x001 인스턴스의 value 값이 10에서 20으로 변경하는데 dataA와 dataB는 같은
x001인스턴스를 참조하기 때문에 dataA.value, dataB.value는 둘다 같은 값인 20을 출력한다.
기본형 vs 참조형 - 메서드 호출
- 기본형: 메서드로 기본형 데이터를 전달하면, 해당 값이 복사되어 전달된다. 이 경우, 메서드 내부에서 매개변수(파라미터)의 값을 변경해도, 호출자의 변수 값에는 영향이 없다.
- 참조형: 메서드로 참조형 데이터를 전달하면, 참조값이 복사되어 전달된다. 이 경우, 메서드 내부에서 매개변수(파라미터)로 전달된 객체의 멤버 변수를 변경하면, 호출자의 객체도 변경된다.
참조형 메서드 호출 - 활용
package ref;
public class Method2 {
public static void main(String[] args) {
Student student1 = createStudent("학생1", 15, 90);
Student student2 = createStudent("학생2", 16, 80);
printStudent(student1);
printStudent(student2);
}
static Student createStudent(String name, int age, int grade) {
Student student = new Student();
student.name = name;
student.age = age;
student.grade = grade;
return student;
}
static void printStudent(Student student1) {
System.out.println("이름:" + student1.name + " 나이:" + student1.age + " 성적:" + student1.grade);
}
함수 진행과
Student student1 = createStudent("학생1", 15, 90) //메서드 호출후 결과 반환
Student student1 = student(x001) //참조형인 student를 반환
Student student1 = x001 //student의 참조값 대입
student1 = x001
createStudent() 는 생성한 Student 인스턴스의 참조값을 반환한다. 이렇게 반환된 참조값을 student1 변수 에 저장했다. 앞으로는 student1 을 통해 Student 인스턴스를 사용할 수 있다.
변수와 초기화
변수의 종류
- 멤버 변수(필드): 클래스에 선언
- 지역 변수: 메서드에 선언, 매개변수도 지역변수의 한 종류이다.
변수의 값 초기화
- 멤버 변수: 자동 초기화
- 인스턴스의 멤버변수는 인스턴스를 생성할 때 자동으로 초기화된다.
- 숫자( int )= 0 , boolean = false , 참조형 = null ( null 값은 참조할 대상이 없다는 뜻으로 사용 된다.)
- 개발자가 초기값을 직접 지정 가능
- 지역 변수: 수동 초기화
- 지역 변수는 항상 직접 초기화 해야한다.
null
package ref;
public class Data {
int value;
}
package ref;
public class NullMain1 {
public static void main(String[] args) {
Data data = null;
System.out.println("1. data = " + data);
data = new Data();
System.out.println("2. data = " + data);
data = null;
System.out.println("3. data = " + data);
}
}
실행 결과 ```
1. data = null
2. data = ref.Data@x001
3. data = null
마지막에 data에 null값을 할당했다. 이렇게 하면 data변수는 앞에서 만든 data 인스턴스를 더는 참조하지 않는다.
이렇게 아무도 참조하지 않는 인스턴스는 사용되지 않고 메모리 용량만 차지하기 때문에 JVM의 GC(가비지 컬렉션)가 더 이상 사용하지 않는 인스턴스라 판단하고 해당 인스턴스를 자동으로 메모리에서 제거해준다.
NullPointerException
package ref;
public class NullMain2 {
public static void main(String[] args) {
Data data = null;
data.value = 10;// NullPointerException 예외 발생
System.out.println("data = " + data.value);
}
}
data참좋ㅇ 변수에는 null값이 들어가 있는데 data.value = 10이라고 함녀 참조할 주소가 존재하지 않아
java.lang.NullPointerException이 발생하고, 프로그램이 종료된다.
멤버변수와 null
package ref;
public class Data {
int value;
}
package ref;
public class BigData {
Data data;
int count;
}
package ref;
public class NullMain3 {
public static void main(String[] args) {
BigData bigData = new BigData();
System.out.println("bigData.count=" + bigData.count);
System.out.println("bigData.data=" + bigData.data);
//NullPointerException
System.out.println("bigData.data.value=" + bigData.data.value);
}
}
실행 결과
bigData.count=0
bigData.data=null
Exception in thread "main" java.lang.NullPointerException: Cannot read field
"value" because "bigData.data" is null
at ref.NullMain3.main(NullMain3.java:10)
BigData 를 생성하면 BigData 의 인스턴스가 생성된다. 이때 BigData 인스턴스의 멤버 변수에 초기화가 일어나 는데, BigData 의 data 멤버 변수는 참조형이므로 null 로 초기화 된다. count 멤버 변수는 숫자이므로 0 으로 초기화된다.
이때 bigData.data.value 를 출력하면 data 의 값이 null 이므로 null 에 . (dot)을 찍게 되고, 따라서 참조 할 곳이 없으므로 NullPointerException 예외가 발생한다.
이런 문제를 해결하려면 Data인스턴스를 만들고 BigData.data 멤버변수에 참조값을 할당하면 된다.
'코딩' 카테고리의 다른 글
[ Java ] 실전자바-기본편 5. 패키지 (0) | 2024.02.13 |
---|---|
[ Java ] 실전자바-기본편 3.객체 지향 프로그래밍 (1) | 2024.02.11 |
[ Java ] 실전자바-기본편 1.클래스와 데이터 (1) | 2024.02.09 |
[ Java ] 자바-입문 8.배열 (1) | 2024.02.07 |
[ Java ] 자바-입문 7.Scanner (0) | 2024.02.06 |