Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

개발자입니다

[비트캠프] 41일차(9주차1일) - Java(메서드) 본문

네이버클라우드 AIaaS 개발자 양성과정 1기/Java

[비트캠프] 41일차(9주차1일) - Java(메서드)

끈기JK 2023. 1. 2. 12:40

 

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장 문자열과 수, 수학