confluence를 사용했던 것처럼 정리해보려고 노력 중이다...
이번 장은 코드가 많아서 나눠 게시글을 올리려고 한다.
책은 [Do it! JAVA 완전 정복]을 읽고 있다. 개념 정리도 잘 돼있고, 코드도 이해하기 쉬우며
무엇보다 책 자체의 가독성이 좋다!!
진작 살 걸 그랬다...
1. 필드
1.1 필드와 지역 변수의 구분
1.1.1 개념
- 필드 : 클래스에 포함된 변수로, 객체의 속성값을 지정할 수 있음
- 지역 변수 : 메서드에 포함된 변수
1.1.2 구분 방법
- 클래스의 중괄호 안에 선언된 변수는 필드, 메서드의 중괄호 안에 선언된 변수는 지역 변수
- 필드는 힙 메모리의 객체 내부에 생성되며, 지역 변수는 스택 메모리에 생성된다.
1.1.3 정리
- 즉, 힙 메모리의 객체 안에 저장되는 '필드'는 객체가 사라지지 않는 한 절대로 삭제되지 않는다.
- 하지만 스택 메모리의 변수인 '지역 변수'는 선언된 메서드 중괄호가 닫히면서 메서드가 종료되면 삭제된다.
💡 이때 1개의 메서드 안에 선언된 모든 지역 변수들의 집합을 '프레임'이라고 한다.
💡 스택 메모리는 Last In First Out(LIFO) 구조를 띤다.
1.1.4 이때까지 실습
package study_class;
class A {
//필드 변수 2개 생성
int m = 3;
int n = 4;
void work1() {
//지역 변수 생성
int k = 5;
System.out.println(k);
//work2() 안에 정의된 지역 변수를 스택 메모리에 추가
work2(3);
}
void work2(int i) {
//지역 변수 생성
int j = 4;
System.out.println(i+j);
}
}
public class Class_study {
public static void main(String[] args) {
//객체 생성
A a = new A();
//필드값 출력
System.out.println(a.m);
System.out.println(a.n);
//메서드 호출, work1() 안에 정의된 지역 변수를 스택 메모리에 추가
a.work1();
}
}
1.1.5 필드와 지역변수의 또다른 차이점
- 또다른 차이점이 있다면 바로 초깃값이다.
- 필드는 직접 초기화하지 않아도 강제로 초기화되지만, 지역 변수는 직접 초기화 하지 않으면 빈 공간이 그대로 있어 값을 출력하고자 할 때 오류가 발생한다.
- 즉, 힙 영역에 저장되는 필드는 초깃값이 없으면 강제 초기화되며, 스택 영역의 지역 변수는 강제로 초기화되지 않는다.
package study_class;
class A {
boolean m1;
int m2;
double m3;
String m4;
void printFieldValue() {
System.out.println(m1);
System.out.println(m2);
System.out.println(m3);
System.out.println(m4);
}
void printLocalVariable() {
int k;
// System.out.println(k);
// 지역 변수를 초기화하지 않아 에러 발생함
}
}
public class Class_study {
public static void main(String[] args) {
A a = new A();
a.printFieldValue();
}
}
2. 메서드
2.1 메서드 정의하기
메서드는 클래스의 기능에 해당하는 요소다.
메서드 정의의 문법적 구조는 아래와 같다.
자바 제어자 리턴(반환) 타입 메서드명(입력매개변수) {
메서드 내용
}
public static int sum(int a, int b) {
//메서드 내용
}
위의 예문은 입력값으로 int형 2개의 값을 입력받아 처리하며, 메서드가 종료된 이후에 int 값을 return 한다는 뜻이다.
C언어를 배웠다면 많이 마주친 return일 것이다...
- 리턴 타입 : 메서드 종료 이후 변환/반환되는 값의 자료형
- 입력매개변수 : 메서드를 호출할 때 전달되는 값의 자료형과 전달받은 값을 저장할 지역 변수명을 정의
- 중괄호 안 메서드 내용 : 메서드가 수행해야 할 기능
2.2 여러 리턴 타입의 메서드
2.2.1 리턴 타입이 void, 입력매개변수는 없는 메서드
void print() {
System.out.println("안녕");
}
- void는 return 값이 없다는 것을 의미한다.
2.2.2 리턴 타입이 int, 입력매개변수가 없는 메서드
int data() {
return 3;
}
- 리턴 타입이 int, 호출 후에는 3의 값이 반환된다.
2.2.3 리턴 타입이 double, 입력매개변수가 2개
double sum(int a, double b) {
return a+b;
}
- int와 double형 데이터를 하나씩 받아서 둘을 합산, double 형태로 리턴한다.
2.2.4 리턴 타입이 void이나, return 키워드 사용
void printMonth(int m) {
if(m<0 || m>12) {
System.out.println("잘못된 입력");
return; //메서드 종료
}
System.out.println(m + "월 입니다.");
}
- 이때 return은 반환을 의미하는 것이 아닌, 메서드를 종료하라는 의미다.
2.3 메서드 호출하기
2.3.1 클래스 외부에서 메서드를 호출해보자
- 메서드도 클래스의 멤버로, 객체 안에 존재한다.
- 때문에 클래스 외부에서 메서드를 사용하려면 먼저 객체를 생성해야 한다.
- 그리고 객체의 위치를 저장하고 있는 참조 변수를 이용해 메서드를 호출해야 한다.
package study_class;
class A {
//리턴 타입 void, 입력매개변수 없음.
void print() {
System.out.println("안녕");
}
//리턴 타입 int, 입력매개변수 없음.
int data() {
return 3;
}
//리턴 타입 double, 입력매개변수 2개
double sum(int a, double b) {
return a+b;
}
//리턴 타입 void, 내부에 리턴 포함(함수 종료)
void printMonth(int m) {
if(m<0 || m>12) {
System.out.println("잘못된 입력.");
return;
}
System.out.println(m+"월입니다.");
}
}
public class Class_study {
public static void main(String[] args) {
//객체 생성
A a = new A();
//매서드 호출(멤버 활용)
a.print();
int k = a.data();
a.data();
System.out.println(k);
double result = a.sum(3, 5.2);
System.out.println(result);
a.printMonth(5);
a.printMonth(15);
}
}
2.3.2 클래스 내부에서 메서드 호출하기
- 클래스 내부에 있는 메서드끼리는 객체를 생성하지 않고 서로를 호출할 수 있다.
- 같은 멤버끼리는 클래스 내부에서 얼마든지 객체를 생성하지 않고 서로를 호출할 수 있다는 뜻이다.
- 단, 메서드 앞에 static이 붙어 있을 때는 static이 붙은 필드 또는 메서드만 호출할 수 있다.
package study_class;
public class Class_study {
public static void main(String[] args) {
//같은 클래스 안에 있는 내부 메서드 호출
print();
int a = twice(3);
System.out.println(a);
double b = sum(a, 5.8);
System.out.println(b);
}
public static void print() {
System.out.println("안녕");
}
public static int twice(int k) {
return k*2;
}
public static double sum(int m, double n) {
return m+n;
}
}
2.3.3 입력매개변수가 배열인 메서드 호출
- 입력매개변수를 배열로 사용할 땐, 배열의 선언/초기화를 주의해야 한다.,
- 주석처리한 printArray({1, 2, 3});처럼 초깃값만 넘겨주면 오류가 발생한다.
package study_class;
import java.util.Arrays;
public class Class_study {
public static void main(String[] args) {
//배열을 입력매개변수로 하는 메서드 호출
int[] a = new int[] {1, 2, 3};
printArray(a);
printArray(new int[] {1, 2, 3});
//printArray({1, 2, 3});
}
public static void printArray(int[] a) {
System.out.println(Arrays.toString(a));
}
}
2.3.4 기본 자료형 입력매개변수와 참조 자료형 입력매개변수의 차이
- 배열과 같은 참조 자료형이 입력매개변수로 넘겨질 땐 실제 객체가 전달되는 것이 아니라 객체의 위칫값이 전달된다.
- 기본 자료형을 입력매개변수로 전달하면 전달받은 메서드는 값을 복사해 사용한다.
- 즉 메서드 twice() 실행이 완료되고도, main() frame 내 a는 변하지 않는 것이다.
package study_class;
public class Class_study {
public static void main(String[] args) {
int a = 3; //a는 main() 함수의 지역 변수 a다.
int result1 = twice(3);
System.out.println(result1);
int result2 = twice(a);
System.out.println(result2);
System.out.println(a);
}
public static int twice(int a) {
a = a*2; //a는 twice의 지역 변수 a다.
return a;
}
}
package study_class;
import java.util.Arrays;
public class Class_study {
public static void main(String[] args) {
int[] array = new int[] {1, 2, 3};
modifyData(array);
printArray(array);
}
public static void modifyData(int[] a) {
a[0] = 4;
a[1] = 5;
a[2] = 6;
}
public static void printArray(int[] a) {
System.out.println(Arrays.toString(a));
}
}
- 반면에 참조 자료형을 입력매개변수로 넘겼을 때를 보면 값이 바뀐다.
- 입력매개변수로 넘겨진 변수의 스택 메모리값이 복사돼 사용되는 것은 동일하나, 참조 자료형은 스택 메모리에 객체의 참좃값(윗치값)을 저장하고 있다.
- 까닭에 실제 객체가 아닌 객체의 참좃값이 전달돼 복사되고, 호출한 메서드와 호출된 메서드에서 모두 동일한 객체를 바라보게 된다.
- 그러므로 호출된 메서드에서 객체의 값을 변경한 후 호출한 메서드로 돌아오면 값이 바뀌게 된다.
2.3.5 오버로딩된 메서드
- 입력매개변수의 개수나 자료형이 다른 여러 개의 동일한 이름을 지닌 메서드를 같은 공간에 정의하는 것
- 이를 이해하기 위해선 메서드 시그너처의 의미를 알아야 한다.
- 메서드 시그너처는 메서드명과 입력매개변수의 자료형을 말하는데, 메서드를 구분하는 기준 역할을 한다.
- 자바 가상 머신은 메서드 시그너처가 다르면 메서드명이 동일해도 다른 메서드로 인식하는데 이를 이용한 것이 메서드 오버로딩이다.
- 아래 색칠된 것이 바로 메서드 시그너처이다.
리턴 타입 메서드명 (자료형 변수명, 자료형 변수명, ...) {
}
int sum (int a, int b) {
return 3;
}
package study_class;
public class Class_study {
public static void main(String[] args) {
print();
print(3);
print(5.8);
print(2, 5);
}
public static void print() {
System.out.println("데이터가 없습니다.");
}
public static void print(int a) {
System.out.println(a);
}
public static void print(double a) {
System.out.println(a);
}
/*
* 위의 것 void print(double a){}와 중복된다
public static void print(double b) {
System.out.println(b);
}
*/
public static void print(int a, int b) {
System.out.println("a: " + a + " b: " + b);
}
/*
* void print(int a, int b){}와 중복된다.
public static int print(int a, int b) {
System.out.println("a: " + a + " b: " + b);
return a+b;
}
*/
}
2.3.6 가변 길이 배열 입력매개변수 메서드
- 개수가 정해지지 않은 가변 길이의 입력을 받는 입력매개변수로 입력된 값들을 배열로 저장하는 것이다.
- 배열의 크기는 함수가 호출될 때 전달된 입력값의 개수로 정해진다.
- 오버로딩만 사용될 떄랑 달리, 단 1개의 메서드만 정의해 모든 메서드 호출에 대응할 수 있게 된다.
리턴 타입 메서드명 (자료형... 참조 변수명) {
//메서드 내용
}
package study_class;
//import java.util.Arrays;
//배열의 출력방법3에서 사용
public class Class_study {
public static void main(String[] args) {
//method1(int...values)
method1(1, 2);
method1(1, 2, 3);
method1();
//method2(String...values)
method2("안녕", "방가");
method2("땡큐", "베리", "감사");
method2();
}
public static void method1(int...values) {
System.out.println("배열의 길이 : " + values.length);
/* 배열의 출력방법 1
for(int i=0; i<values.length; i++){
System.out.print(values[i] + " ");
} */
//배열의 출력방법 2
for(int k: values) {
System.out.print(k + " ");
}
/* 배열의 출력방법 3
System.out.println(Arrays.toString(values));
*/
System.out.println();
}
public static void method2(String...values) {
System.out.println("배열의 길이 : " + values.length);
/* 배열의 출력방법 1
for(int i=0; i<values.length; i++){
System.out.print(values[i] + " ");
} */
//배열의 출력방법 2
for(String k: values) {
System.out.print(k + " ");
}
/* 배열의 출력방법 3
System.out.println(Arrays.toString(values));
*/
System.out.println();
}
}
여기까지가 메서드의 내용이다. 생성자부터는 2 게시글로 작성하려고 한다.
위의 예제... 책 펴낸 이의 세대가 보이는 것 같다...
'Study > JAVA' 카테고리의 다른 글
[JAVA] 8장 - 클래스 외부 구성 요소 (0) | 2022.10.02 |
---|---|
[JAVA] 7장 - 클래스 내부 구성 요소(2) (0) | 2022.10.02 |
[JAVA] 6장 - 클래스와 객체 (0) | 2022.09.30 |
[JAVA] 2장 - 자료형(1) (0) | 2022.05.14 |
[JAVA] 1장 - 소스 코드 구조와 콘솔 출력, 문자열 관련 (0) | 2022.05.10 |