개발자입니다
[비트캠프] 41일차(9주차1일) - Java(메서드) 본문
Parameter와 argument
함수 정의할때 넘겨줄 변수명을 parameter라 한다.
함수 사용할때 입력하는 값을 argument라 한다.
가변 파라미터와 배열
String[] arr = {"김구", "유관순", "안중근", "윤봉길"}; 하면 메모리가 할당되고 주소 200이 들어간다.
hello(arr); 하면 arr에 주소 200이 대입된다.
디바이스 드라이버에서 메모리에 잘못 접근하면 블루스크린이 뜬다. 운영체제를 경유하지 않고 하드디스크에 접근하는 것은 디바이스 드라이버 밖에 없다. 일반 프로그램은 블루스크린이 뜰 수 없다.
call by value
swap(a, b); 에서 a, b는 int 값(primitive type의 값)이다.
call by reference
swap(arr) 에서 arr은 배열 주소(reference)이다.
call by value와 메모리 상태
public class Exam0310 {
static void swap(int a, int b) {
System.out.printf("swap(): a=%d, b=%d\n", a, b);
int temp = a;
a = b;
b = temp;
System.out.printf("swap(): a=%d, b=%d\n", a, b);
}
public static void main(String[] args) {
int a = 100;
int b = 200;
// swap() 호출할 때 a 변수의 값과 b 변수의 값을 넘긴다.
// => 그래서 "call by value"라 부른다.
// => 비록 swap()에서 a와 b라는 이름의 변수가 있지만,
// 이 변수는 main()에 있는 변수와 다른 변수이다.
swap(a, b);
System.out.printf("main(): a=%d, b=%d\n", a, b);
}
}
Stack은 호출 메서드의 로컬 변수가 놓인다.
Heap은 new 명령으로 만든 인스턴스 변수가 놓인다.
Method Area는 실행할 클래스 코드가 놓인다 ← bytecode를 구조화시켜 메모리에 배치한다.
ⓞ main() 실행
main() 실행하면 메모리의 Stack 영역에 args, a, b 가 준비된다.
메서드를 호출하면 메서드가 사용할 로컬 변수가 "스택 메모리 영역"에 준비된다.
① swap() 실행
main() 이 쭉 실행되다가 swap() 을 실행한다.
Stack에 swap() 의 Frame이 생성되고 안에 a, b, temp 이름을 가진 로컬 변수가 생성된다.
② return
return 하게 되고 swap() 을 실행하는 동안 사용한 메모리는 제거된다.
③ 호출 끝
main() 메서드가 사용한 메모리도 제거된다.
④ JVM 실행 종료
JVM이 사용했던 메모리는 OS에 의해 강제 회수된다.
call by reference와 메모리 상태
public class Exam0320 {
static void swap(int[] arr) {
System.out.printf("swap(): arr[0]=%d, arr[1]=%d\n", arr[0], arr[1]);
int temp = arr[0];
arr[0] = arr[1];
arr[1] = temp;
System.out.printf("swap(): arr[0]=%d, arr[1]=%d\n", arr[0], arr[1]);
}
public static void main(String[] args) {
int[] arr = new int[] {100, 200};
swap(arr); // 배열 인스턴스(메모리)를 넘기는 것이 아니다.
// 주소를 넘기는 것이다.
// 그래서 "call by reference" 라 부른다.
System.out.printf("main(): arr[0]=%d, arr[1]=%d\n", arr[0], arr[1]);
}
}
① 프로그램 실행
$ java Exam0320 입력하면 프로그램 실행한다. HDD 에서 RAM(Method Area)에 "클래스 로딩" 된다.
② main() 실행
main() 실행되고 Stack에 frame 생성되어 로컬 변수 args, arr 준비한다. 배열 인스턴스가 Heap에 생성된다. 그 주소가 로컬 변수 arr에 저장된다.
③ swap 실행
swap() 실행되고 Stack에 frame 생성되어 로컬 변수 arr, temp 준비한다. swap() 괄호안에 배열의 주소(reference)가 입력된다.
④ return
swap() 호출 끝나면 return 되고 Stack 메모리에서 삭제된다.
⑤ main() 종료
main() 종료되어 Stack 메모리에서 삭제된다.
⑥ JVM 종료
JVM 종료되어 운영체제에 의해 메모리 회수된다.
call by reference 와 객체
public class Exam0330 {
// main()에서 만든 int a와 int b의 값을 바꾸고 싶다면,
// primitive data type 값을 직접 넘기지 말고
// 객체에 담아 넘겨라!
static class MyObject {
// => class 는 메모리의 구조를 설계하는 문법이다.
// => new 명령을 이용하여 변수를 생성할 수 있다.
int a;
int b;
}
static void swap(MyObject ref) {
System.out.printf("swap(): a=%d, b=%d\n", ref.a, ref.b);
int temp = ref.a;
ref.a = ref.b;
ref.b = temp;
System.out.printf("swap(): a=%d, b=%d\n", ref.a, ref.b);
}
public static void main(String[] args) {
// MyObject 설계도에 따라 int a와 int b 메모리를 만든다.
// 그리고 그 메모리(인스턴스=객체)의 주소를 ref 변수에 저장한다.
MyObject ref = new MyObject();
ref.a = 100;
ref.b = 200;
// a, b 변수가 들어 있는 인스턴스(객체=메모리)의 주소를
// swap()에 넘긴다. => 그래서 "call by reference"인 것이다.
swap(ref);
System.out.printf("main(): a=%d, b=%d\n", ref.a, ref.b);
}
}
① 클래스 로딩
$ java Exam0330 입력하면 Method Area에 클래스 로딩한다.
② main() 호출
Stack에 main()의 frame 생성되고 로컬 변수 args, ref 할당된다.
③ MyObject 클래스 로딩 및 변수 준비
MyObject()는 메모리 설계도 = data type = class 이다.
3-1) MyObject 클래스 로딩
Method Area에 클래스 로딩된다.
3-2) MyObject 설계도에 따라 변수를 준비
Heap에 MyObject의 인스턴스 생성 및 Stack의 ref에 주소 저장한다.
④ 인스턴스 변수에 값 저장
Head의 주소 200에 변수 a에 100, b에 200이 저장된다.
⑤ swap() 호출
Stack에 swap()의 frame 생성되고 로컬 변수 ref, temp 할당된다.
temp에 Heap의 주소 200의 변수 a 값 100이 저장되고 a에 b의 값 200이 저장된다. b에 temp의 값 100이 저장된다.
return하면 Stack의 메모리 해제된다.
⑥ main() 호출 끝
main() 호출 끝나면 Stack의 메모리 해제된다.
⑦ JVM 종료
JVM 종료되어 운영체제에 의해 메모리 회수된다.
reference 리턴하기
public class Exam0340 {
// swap()에서 만든 int a와 int b의 값을 main()에서 사용하기
// primitive data type 값을 객체에 담아 넘겨라!
static class MyObject {
int a;
int b;
}
static MyObject swap(int a, int b) {
MyObject ref = new MyObject();
ref.a = b;
ref.b = a;
return ref;
}
public static void main(String[] args) {
int a = 100;
int b = 200;
MyObject ref = swap(a, b);
System.out.printf("main(): ref.a=%d, ref.b=%d\n", ref.a, ref.b);
}
}
① 실행
$ java Exam0340 입력하면 Method Area에 class Exam0340 이 로딩된다.
② main() 호출
Stack에 main() 의 frame 생성되고 로컬 변수 args, a, b, ref 메모리 확보된다.
③ swap() 호출
3-1) MyObject 클래스 로딩
Method Area에 class MyObject 가 로딩된다.
3-2) MyObject의 인스턴스 변수 생성
Heap에 배열 메모리 확보 후 ref에 주소 저장된다.
3-3) 인스턴스 변수 값 저장
Head의 인스턴스 변수 a에 100, b에 200 저장된다.
3-4) 인스턴스 주소 리턴
Heap의 주소 200이 리턴된다. Stack의 메모리 해제된다.
④ main() 호출 끝
Stack의 메모리 해제된다.
⑤ JVM 종료
JVM 종료되어 운영체제에 의해 메모리 회수된다.
main() 메서드
# 메서드 : main() 메서드 - 프로그램 아규먼트
$ java Exam0520 aa bbb cccc ddddd 하면 String 배열을 생성해서 그 주소를 전달한다.
C:\Users\bitcamp\git\bitcamp-ncp\eomcs-java-lang\app>java -cp bin/main com.eomcs.lang.ex07.Exam0520 aa bbb cccc ddddd
[aa]
[bbb]
[cccc]
[ddddd]
종료!
public class Exam0520 {
// 프로그램 아규먼트
// - jvm을 실행할 때 프로그램에 전달하는 값
// - 예)
// > java -cp bin Exam0520 aaa bbb cccc
// aaa bbb cccc 가 프로그램 아규먼트이다.
//
public static void main(String[] args) {
// 프로그램 아규먼트는 스트링 배열에 담겨서 main()를 호출할 때
// 넘어온다.
// 프로그램 아규먼트는 공백을 기준으로 문자열을 잘라서 배열을 만든다.
// 아규먼트가 없으면 빈 배열이 넘어온다.
//
for (String value : args) {
System.out.printf("[%s]\n", value);
}
System.out.println("종료!");
}
}
# JVM 아규먼트
-Da=ok 식으로 JVM 아규먼트를 전달할 수 있다.
C:\Users\bitcamp\git\bitcamp-ncp\eomcs-java-lang\app>java -cp bin/main -Da=ok -Db=no -Dc=haha com.eomcs.lang.ex07.Exam0610
ok
no
haha
public class Exam0610 {
public static void main(String[] 변수명은상관없다) {
// JVM 아규먼트?
// - JVM에게 전달하는 값
// - 형식
// $java -cp ./bin/main -D이름=값 -D이름=값 -D이름=값 com.eomcs.basic.ex07.Exam0610
//
// JVM 아규먼트의 값 꺼내기
// => System.getProperty("이름");
//
String value1 = System.getProperty("a");
String value2 = System.getProperty("b");
String value3 = System.getProperty("c");
System.out.println(value1);
System.out.println(value2);
System.out.println(value3);
}
}
# JVM 아규먼트 응용 II
JVM 기본 프로퍼티를 모두 출력한다.
public class Exam0630 {
public static void main(String[] 변수명은상관없다) {
// JVM에 기본으로 설정되어 있는 프로퍼티를 모두 출력하라!
//
// JVM의 전체 프로퍼티 목록 가져오기
java.util.Properties props = System.getProperties();
// 1) Properties 객체에 저장되어 있는 값의 이름(key)을 알아낸다.
// => keySet() 이 리턴하는 것은 이름이 들어 있는 집합이다.
java.util.Set keySet = props.keySet();
// 이름이 들어 있는 집합에서 한 개의 이름을 가져와서 그 이름으로 저장된 값을 꺼낸다.
// => 집합에서 꺼낸 이름이 실제는 String 타입이지만,
// 문법 상으로는 Object로 되어 있어서
// 변수를 선언할 때 Object 타입으로 변수를 선언해야 한다.
for (Object key : keySet) {
// getProperty()에 이름을 전달할 때는 String 을 전달해야 한다.
// 물론 key에 들어 있는 것은 String 이 맞지만
// 문법 상으로는 key 변수가 Object로 되어 있다.
// 따라서 getProperty()에 key 변수에 들어 있는 값을 전달할 때
// String 이라고 컴파일러에게 알려줄 필요가 있다.
String value = props.getProperty((String) key);
System.out.printf("%s ==> %s\n", key, value);
}
// 위 문장을 다음과 같이 바꿔도 된다.
// for (Object key : keySet) {
// String value = System.getProperty((String) key);
// System.out.printf("%s = %s\n", key, value);
// }
}
}
콘솔 결과
java.specification.version ==> 17
sun.cpu.isalist ==> amd64
sun.jnu.encoding ==> MS949
java.class.path ==> C:\Users\bitcamp\git\bitcamp-ncp\eomcs-java-lang\app\bin\main;C:\Users\bitcamp\scoop\apps\gradle\current\.gradle\caches\modules-2\files-2.1\com.google.guava\guava\31.1-jre\60458f877d055d0c9114d9e1a2efb737b4bc282c\guava-31.1-jre.jar;C:\Users\bitcamp\scoop\apps\gradle\current\.gradle\caches\modules-2\files-2.1\com.google.guava\failureaccess\1.0.1\1dcf1de382a0bf95a3d8b0849546c88bac1292c9\failureaccess-1.0.1.jar;C:\Users\bitcamp\scoop\apps\gradle\current\.gradle\caches\modules-2\files-2.1\com.google.guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\b421526c5f297295adef1c886e5246c39d4ac629\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\bitcamp\scoop\apps\gradle\current\.gradle\caches\modules-2\files-2.1\com.google.code.findbugs\jsr305\3.0.2\25ea2e8b0c338a877313bd4672d3fe056ea78f0d\jsr305-3.0.2.jar;C:\Users\bitcamp\scoop\apps\gradle\current\.gradle\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.12.0\d5692f0526415fcc6de94bb5bfbd3afd9dd3b3e5\checker-qual-3.12.0.jar;C:\Users\bitcamp\scoop\apps\gradle\current\.gradle\caches\modules-2\files-2.1\com.google.errorprone\error_prone_annotations\2.11.0\c5a0ace696d3f8b1c1d8cc036d8c03cc0cbe6b69\error_prone_annotations-2.11.0.jar;C:\Users\bitcamp\scoop\apps\gradle\current\.gradle\caches\modules-2\files-2.1\com.google.j2objc\j2objc-annotations\1.3\ba035118bc8bac37d7eff77700720999acd9986d\j2objc-annotations-1.3.jar
java.vm.vendor ==> Oracle Corporation
sun.arch.data.model ==> 64
user.variant ==>
java.vendor.url ==> https://java.oracle.com/
java.vm.specification.version ==> 17
os.name ==> Windows 11
sun.java.launcher ==> SUN_STANDARD
user.country ==> KR
sun.boot.library.path ==> C:\Program Files\Java\jdk-17.0.5\bin
sun.java.command ==> com.eomcs.lang.ex07.Exam0630
jdk.debug ==> release
sun.cpu.endian ==> little
user.home ==> C:\Users\bitcamp
user.language ==> ko
java.specification.vendor ==> Oracle Corporation
java.version.date ==> 2022-10-18
java.home ==> C:\Program Files\Java\jdk-17.0.5
file.separator ==> \
java.vm.compressedOopsMode ==> Zero based
line.separator ==>
java.vm.specification.vendor ==> Oracle Corporation
java.specification.name ==> Java Platform API Specification
user.script ==>
sun.management.compiler ==> HotSpot 64-Bit Tiered Compilers
java.runtime.version ==> 17.0.5+9-LTS-191
user.name ==> bitcamp
path.separator ==> ;
os.version ==> 10.0
java.runtime.name ==> Java(TM) SE Runtime Environment
file.encoding ==> UTF-8
java.vm.name ==> Java HotSpot(TM) 64-Bit Server VM
java.vendor.url.bug ==> https://bugreport.java.com/bugreport/
java.io.tmpdir ==> C:\Users\bitcamp\AppData\Local\Temp\
java.version ==> 17.0.5
user.dir ==> C:\Users\bitcamp\git\bitcamp-ncp\eomcs-java-lang\app
os.arch ==> amd64
java.vm.specification.name ==> Java Virtual Machine Specification
sun.os.patch.level ==>
native.encoding ==> MS949
java.library.path ==> C:\Program Files\Java\jdk-17.0.5\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Program Files/Java/jdk-17.0.5/bin/server;C:/Program Files/Java/jdk-17.0.5/bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files\Bandizip\;C:\HashiCorp\Vagrant\bin;C:\Program Files\nodejs\;C:\ProgramData\chocolatey\bin;C:\Users\bitcamp\scoop\shims;C:\Program Files\Java\jdk-17.0.5\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files\Bandizip\;C:\HashiCorp\Vagrant\bin;C:\Program Files\nodejs\;C:\ProgramData\chocolatey\bin;C:\Program Files\Java\jdk-17.0.5\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files\Bandizip\;C:\HashiCorp\Vagrant\bin;C:\Program Files\nodejs\;C:\ProgramData\chocolatey\bin;;C:\Users\bitcamp\eclipse\jee-2022-12\eclipse;;.
java.vm.info ==> mixed mode, sharing
java.vendor ==> Oracle Corporation
java.vm.version ==> 17.0.5+9-LTS-191
sun.io.unicode.encoding ==> UnicodeLittle
java.class.version ==> 61.0
변수
static int v1; ← 클래스 필드(field, 변수) = 스태틱 필드(field, 변수) ← 클래스 로딩시 "Method Area" 영역에 생성된다.
int v2; ← 인스턴스 필드 = 논스태틱(non-static) 필드 ← new 명령 실행시 "Heap" 영역에 생성된다.
void m(int v3) { ← 로컬 변수 = 파라미터
int v4; ← 로컬 변수
} ← 로컬 변수는 메서드 호출 시 "JVM Stack" 영영에 생성된다.
조언
*천재는 자기보다 더 천재를 만나면 회복 불가능하게 무너진다. 보통 사람은 무너지지 않는다.
*초보는 과도한 객체지향 기법을 남발해야 한다.
*C의 단점을 극복한 언어가 Rust이다. 파이어폭스를 만든 모질라 재단에서 만들었다.
과제
코딩 개념 잡는 자바 코딩 문제집 풀기
1장 문자열과 수, 수학
'네이버클라우드 AIaaS 개발자 양성과정 1기 > Java' 카테고리의 다른 글
[Java] 예제 소스 정리 - 클래스(인스턴스, public, default, 중첩 클래스) (0) | 2023.01.03 |
---|---|
[비트캠프] 42일차(9주차2일) - Java(클래스) (0) | 2023.01.03 |
[Java] 예제 소스 정리 - 콘솔 출력 (1) | 2022.12.30 |
[Java] 예제 소스 정리 - 메서드(개념, 가변 파라미터, 배열 파라미터, call by value, call by reference, main(), JVM 아규먼트) (0) | 2022.12.30 |
[비트캠프] 40일차(8주차5일) - Java(클래스), myapp-03~06 실습 (0) | 2022.12.30 |