자바 기본 배우기 -메소드와 JVM의 메모리 구조-

1. 메소드(method)

 

객체가 할 수 있는 행동을 정의

 

어떤 작업을 수행하는 명령문의 집합에 이름을 붙여 놓은 것

 

이름은 소문자로 시작하고 camelCase로 작성하는 것이 관례

 

 

 

접근제한자에서 default의 경우 접근제한자로 아무것도 안쓰면 default

 

return이 없으면 반환값 부분에는 void라고 써야함

 

매개변수들은 없어도 된다

 

1-1) 왜 작성하나?

 

반복적인 코드 사용을 줄인다, 코드 중복을 제거, 코드 양을 줄인다

 

유지보수가 좋다

 

 

1-2) 메소드 선언

 

{}안에 메소드가 해야할 일을 정의함

 

 

1-3) 호출 방법

 

(인스턴스이름).(메소드 이름)으로 접근

 

메소드가 static으로 선언되어 있다면, (클래스 이름).(메소드 이름)으로 접근 가능하다

 

public class Person {
    
    public void info() {
        //메소드 내용 정의
    }
    
    public static void hello() {
        //메소드 내용 정의
    }
}

 

info()의 경우.. 

 

Person p = new Person();

p.info();

 

hello()의 경우 static으로 선언되어, 클래스 영역에 미리 올라가 있어서.. 클래스로 접근 가능

 

Person.hello();

 

 

1-4) 매개변수(parameter)와 인자(argument)

 

매개변수는 메소드에서 사용하는 변수

 

인자는 호출하면서 전달해주는 매개변수의 값

 

하지만 둘을 구분하지 않고 parameter나 argument라고 말하기도 함

 

 

 

매개변수는 아무것도 안써도 된다

 

인자로 전달하면, 묵시적으로 형변환되어 전달된다

 

 

 

byte, short는 int보다 작아서 int로 묵시적 형변환되어 전달

 

하지만 10L, 10.0f, 10.0같은 long, float, double은 int보다 커서 전달되지 않는다

 

그리고 매개변수가 1개인데 2개를 전달하는 p.study(10,10)도 당연히 안된다

 

 

1-5) return type

 

메소드를 선언할 때 지정하며 return이 없다면 void를 사용해야함

 

return type을 작성했다면, 반드시 해당하는 type을 return해야함

 

return type은 하나만 작성 가능하다..

 

하지만 여러개의 값을 return하고 싶다면? 당연히 배열이나 클래스 등으로 return해야지

 

 

1-6) overloading

 

메소드의 이름은 서로 같은데, 매개변수가 다른 메소드를 정의하는 것

 

매개변수의 개수나 순서 혹은 타입이 달라야한다. 이름만 다른 것은 메소드 오버로딩이 아니다

 

예를 들어..

 

info(String name, String hobby)라는 메소드가 있을 때

 

info(String name)은 가능한데

 

info(String n, String h)라고 이름만 바꾸는 것은 메소드 오버로딩이라고 하지 않는다

 

return type이 다른 것은 의미 없다

 

 

파이썬은 type선언을 안하니까 메소드 오버로딩이 없었는데.. 자바는 타입을 선언하다보니 이런게 있네

 

 

2. 클래스와 객체 정리

 

1) 클래스

 

관련 있는 변수와 함수를 묶어 만든 사용자 정의 자료형이다

 

2) 객체

 

하나의 역할을 수행하는 "메소드와 변수(데이터)"의 묶음

 

3) 객체지향 프로그래밍

 

프로그램을 단순히 데이터와 처리 방법으로 나누는 것이 아니라,

 

프로그램을 수많은 객체(object)라는 기본 단위로 나누고 이들의 상호작용으로 서술하는 방식이다

 

 

3. JVM 메모리 구조

 

자바 언어는 메모리 관리를 개발자가 하지 않고 GC(garbage collection)가 관리한다

 

1) garbage collections

 

heap영역(class영역도 포함됨)에 생성된 메모리 관리 담당

 

즉, 이 영역에 더 이상 사용되지 않는 객체들을 찾아 제거함

 

CPU가 한가하거나 메모리가 부족할 때 JVM에 의해 자동적으로 실행됨

 

System.gc()로 직접 호출해서 사용할 수도 있지만,.... 너도 직접 해본적 있다시피

 

이게 호출한다고 언제 작동할지도 모르며, 시스템에 영향을 줄 수 있어 직접 호출하는 것은 절대로 권장하지 않는다

 

 

2) 메모리 영역

 

클래스 영역, 힙 영역, 스택 영역 크게 3가지로 나뉜다

 

 

 

class loader는 *.class 파일을 읽어서 클래스 영역에 클래스 정보, 메소드, static으로 생성한 변수 등을 저장함

 

heap 영역은 new라는 키워드에 의해 생성된 것들이 저장된다

 

스택에 "메소드 수행시 프레임이 할당됨" 이러는데.. 프로그램에서 메소드가 수행되면 스택에 차례대로 쌓여서...

 

결과를 반환하면서 스택에서 빠져나감

 

추가로 어떤 블록 내에 생성되는 지역변수도 스택에 생성

 

 

3) 예시로 이해해보기

 

Person p1 = new Person();
p1.name = "Yang";
p1.age = 45;
p1.hobby = "유튜브";

 

class loader가 Person이라는 클래스의 정보를 읽어 클래스 영역에 올려둔다

 

 

 

main 메소드가 수행되면서 스택에 들어가고.. 변수 p1이 스택에 공간이 생기는데..

 

new Person()이 수행되면서 힙 영역에 인스턴스가 생성되고 해당 주소를 스택의 p1이 저장함

 

 

처음 new Person() 순간 name, age, hobby는 각각의 초기값으로 초기화

 

p1.name  = "Yang"; 하면.. Yang은 string pool에 생성되고, 힙영역의 name이 Yang을 가리키는 주소를 저장

 

 

그리고 p1.age = 45;하면 age에서 직접 45를 저장하고..

 

p1.hobby = "유튜브"; 하면 Yang과 마찬가지로 string pool에 "유튜브"가 생기고 hobby가 해당 값을 가리키는 주소를 저장

 

 

4. static의 특징

 

4-1) 메모리적 특징

 

static으로 선언된 것은 클래스가 로딩되면 클래스 영역에 저장

 

그러므로 클래스당 하나의 메모리 공간만 할당된다

 

static으로 선언이 안된 것은 객체(인스턴스)가 생성 될 경우 다른 영역에 저장된다

 

그러므로 인스턴스당 메모리가 별도로 할당된다.. 인스턴스마다 고유한 영역이 있잖아 거기에 저장

 

4-2) 문법적 특징

 

static은 클래스 이름으로 접근 가능하다.

 

물론 static은 인스턴스 이름으로 접근 가능하지만.. IDE에서 경고를 줌

 

static이 아닌 것은 객체를 생성하고 객체 이름으로 접근 가능하다

 

다음과 같이 정의된 Person 클래스에서 static 변수는 pCount, 나머지는 non-static 변수

 

public class Person {
    static int pCount;
    
    String name;
    int age;
    String hobby;
}

 

name은 non-static 변수니까 인스턴스 이름 p로 접근 가능

 

pCount는 static 변수니까 클래스 이름 Person으로 접근 가능

 

물론 인스턴스 이름 p로도 접근 가능하나, 경고를 받는다

 

public class PersonTest {
    public static void main(String[] args) {
        
        //객체 생성
        Person p = new Person();
        
        //인스턴스 변수
        p.name = "Kim";
        
        //static 변수
        Person.pCount++;
        
        //이것도 가능하지만.. IDE에서 경고를 준다
        p.pCount++;
    }
}

 

static 영역에서는 non-static 영역을 직접 접근이 불가능하며

 

non-static 영역에서는 static 영역에 대한 접근이 가능하다

 

다음 코드를 보자.

 

public class Main {
    
    //Main이라는 클래스 안에 클래스 영역에 작성된..
    //인스턴스 변수
    String str = "문장";
    
    public static void main(String[] args){
        System.out.println(str);
    }
}

 

String str = "문장";은 인스턴스 변수이고 아래 static void main()메소드는 static으로 작성된 메소드

 

static으로 작성된 메소드는.. 클래스 영역에 올라가있고..

 

인스턴스 변수인 String str = "문장";은 new Main()에 의해 인스턴스가 생성되어야 힙 영역에 생기는 변수

 

그러니까 static으로 작성된 main 메소드가 String str보다 먼저 올라와 있으니까...

 

str이 어디있는지 main 메소드는 알수가 없다

 

그래서 System.out.println(str);은 에러가 난다

 

반대로 다음 코드를 보자

 

public class Main {
    
    static String str = "문장";
    
    public void print() {
        System.out.println(str);
    }
}

 

위 코드에서 String str = "문장";은 static으로 선언되어 있어서 이미 클래스 메모리에 올라와 있다

 

따라서 static이 아닌 print() 메소드는 System.out.println(str);로 str이 어디있는지 알 수 있으니까 에러나지 않는다

 

그래서 알고리즘 문제 해결에 static을 보통 전역변수처럼 미리 메모리에 올려놓고 위와 같은 방식을 많이 사용

 

TAGS.

Comments