[Java] 김영한의 실전 자바 - 기본편 섹션1~2 클래스와 데이터, 기본형과 참조형
○ 섹션 1 클래스와 데이터
● 클래스
- 멤버 변수(Member Variable),필드(Field) 필드: 클래스에 정의한 변수들
- 클래스는 관례상 대문자로 시작하고 낙타 표기법을 사용. ex) MemberService
- 클래스: 설계도
- 객체 또는 인스턴스: 실제 메모리에 만들어진 실체
- 객체를 생성하면 자바는 객체에 접근할 수 있는 참조값(주소) 반환
- new 키워드를 통해 객체 생성 후 참조값 반환
- new 는 클래스를 기반으로 메모리에 실제 객체를 만드는 것. 리턴 참조 값을 변수에 저장함으로써 실제 메모리 존재 객체에 접근 가능
● 객체에 값 대입
클래스,객체,인스턴스 정리
클래스: 틀 또는 설계도. 객체가 가져야 할 속성과 기능 정의
객체: 클래스에서 정의한 속성과 기능을 가진 실체
인스턴스: 특정 클래스로부터 생성된 객체. 어떤 클래스에 속해 있는지 강조할 때 사용
● 배열 도입 - 시작
Student[] students = new Student[2];
- Student 타입 변수는 Student 인스턴스 참조값을 보관
- 배열은 아직 참조값을 대입하지 않았기 때문에 null 값으로 초기화
★ 배열에 객체를 보관할때
!!! 자바에서 대입은 항상 변수에 들어 있는 값을 복사한다. !!!
아래의 student1, student2 에는 참조값이 보관되어 있다. 따라서 이 참조값이 배열에 저장된다. 또는 이를 객체에 보관된 참조값을 읽고 복사해서 배열에 대입한다고 표현한다.
students[0] = student1; // x001;
students[1] = student2; // x002;
주의!
변수에는 인스턴스가아니라, 인스턴스 위치를 가리키는 참조값이 들어있다.
● 배열 도입 - 리팩토링
배열 선언 최적화
Student[] students = new Student[]{student1, student2};
for문 최적화
for (int i = 0; i < students.length; i++) {
System.out.println("이름:" + students[i].name + " 나이:" + students[i].age +
...);
향상된 for문
for (Student s : students) {
System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" + s.grade);
}
○ 섹션 2 기본형과 참조형
● 기본형 vs 참조형 1 - 시작
- 기본형(Primitive Type): `int` , `long` , `double` , `boolean` 처럼 변수에 사용할 값을 직접 넣을 수 있는 데이 터 타입
- 참조형(Reference Type): `Student student1` , `int[] students` 와 같이 데이터에 접근하기 위한 참조 (주소)를 저장하는 데이터 타입. 참조형은 객체 또는 배열에 사용된다.
- 기본형은 계산 활용 가능, 참조형은 불가능
참고 - String
String은 사실 클래스라 참조형이지만, 기본형처럼 문자 값을 바로 대입할 수 있다! 이는 나중에 더 자세히 다룬다.
● 기본형 vs 참조형2 - 변수 대입
기본형은 실제 값이 들어있다. 변수 대입은 변수에 들어있는 값을 복사해서 대입한다. 아래를 보면, 값을 복사해 전달하기때문에 각각 본인의 값만 변경됨을 확인 가능하다.
int a = 10;
int b = a;
System.out.println("a = " + a);
System.out.println("b = " + b);
//a 변경
a = 20;
System.out.println("변경 a = 20");
System.out.println("a = " + a);
System.out.println("b = " + b);
//b 변경
b = 30;
System.out.println("변경 b = 30");
System.out.println("a = " + a);
System.out.println("b = " + b);
a = 10
b = 10
변경 a = 20
a = 20
b = 10
변경 b = 30
a = 20
b = 30
이제 참조형에서의 변수 대입을 보자. 아래를 보면, `Data dataB = dataA` 에서, B에 복사된 참조값이 같기 때문에 결국 하나를 변경시 값이 둘다 변경된다.
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
● 기본형 vs 참조형3 - 메서드 호출
- 대원칙: 자바는 항상 변수의 값을 복사해서 대입한다.
- 메서드를 호출할 때 사용하는 매개변수(파라미터)도 결국 변수일 뿐이다. 따라서 메서드 를 호출할 때 매개변수에 값을 전달하는 것도 앞서 설명한 내용과 같이 값을 복사해서 전달한다.
먼저 기본형 파라미터 메서드 호출 예시를 보자.
public class MethodChange1 {
public static void main(String[] args) {
int a = 10;
System.out.println("메서드 호출 전: a = " + a);
changePrimitive(a);
System.out.println("메서드 호출 후: a = " + a);
}
static void changePrimitive(int x) {
x = 20;
}
}
메서드 호출 전: a = 10
메서드 호출 후: a = 10
- 위 그림과 같이 파라미터 x에 a값 10이 대입되고, 메서드안에 x값이 20으로 변경된다.
- 메서드 종료 후, 매개변수 x 또한 제거된다.
이제 참조형 파라미터 메서드 호출 예시를 보자.
public class MethodChange2 {
public static void main(String[] args) {
Data dataA = new Data();
dataA.value = 10;
System.out.println("메서드 호출 전: dataA.value = " + dataA.value);
changeReference(dataA);
System.out.println("메서드 호출 후: dataA.value = " + dataA.value);
}
static void changeReference(Data dataX) {
dataX.value = 20;
}
}
메서드 호출 전: dataA.value = 10
메서드 호출 후: dataA.value = 20
- 메서드를 호출할 때, dataX는 변수 dataA의 값(참조값 x001)을 받는다.
- 참조값을 통해 인스턴스 접근 후 20으로 변경한다.
- 둘다 같은 인스턴스를 참조하기 때문에 둘다 변경된다.
★ 기본형과 참조형 메서드 호출
기본형:
- 값 복사 전달
- 메서드 내부 변경 시 호출자 변수 영향 없음
참조형:
- 참조값 복사 전달
- 메서드 내부 변경 시 호출자 객체도 변경
● 참조형과 메서드 호출 - 활용
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);
}
createStudent() 메서드 안에서 객체 생성 후 메서드 밖에서 객체를 사용할 수 있도록 객체 참조값을 반환한다.
● 변수와 초기화
💚 변수 종류
- 멤버 변수(필드): 클래스에 선언
- 지역 변수: 메서드에 선언, 매개변수도 지역 변수의 한 종류이다.
💚 변수 값 초기화
- 멤버변수: 자동초기화 ex_ 숫자( int)= 0 , boolean = false , 참조형 = null
- 지역변수: 수동 초기화
● null
- data에 null 값을 할당해 인스턴스를 더는 참조하지 않도록 할 수 있다.
- 자바에서는 아무도 참조하지 않는 인스턴스를 JVM GC(가비지 컬렉션)가 자동으로 메모리에서 제거해준다. 해당 객체를 참조하는 곳이 모두 사라지면 GC에 의해 제거된다.
● NullPointerException
참조할 객체 인스턴스가 존재하지 않을때 발생한다.
멤버 변수가 null일때 이는 특히 주의가 필요하다.
public class BigData {
Data data;
int count;
}
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)
위는 null.value가 되므로 예외가 발생한다.
NullPointerException` 이 발생하면 null 값에 . (dot)을 찍었다고 생각하면 문제를 쉽게 찾을 수 있다.
본 내용은 인프런 " 김영한의 실전 자바 - 기본편 " 강의를 정리한 내용입니다.
'Java' 카테고리의 다른 글
[Java] Array / List / ArrayList 차이점 정리 (1) | 2024.04.08 |
---|---|
[Java의 정석] chapter05 배열 array - 요약정리 (0) | 2024.04.08 |
[Java] 김영한의 자바 입문 - 섹션2~3 변수, 연산자 (0) | 2024.03.31 |
[Java] 김영한의 자바 입문 - 섹션1 Hello World 자바란? (0) | 2024.03.30 |
[Java의 정석] chapter02 변수 variable - 요약정리 (1) | 2023.10.20 |