2. 스택(Stack) 메모리와 힙(Heap) 메모리

 스택에는 함수 내에 존재하는 로컬 변수가 저장되고, 힙에는 클래스 내에 존재하는 인스턴스 변수가 저장된다. 실제 객체를 생성할 때 스택과 힙에 어떻게 할당될까? (자바의 메모리 영역이 스택과 힙만 있는 것은 아니지만 객체 생성 시 가장 관련이 있는 것이 두 메모리이다.)

 

 객체가 생성될 때 메모리에서 어떤 일이 일어나는지 살펴보기 위해 앞서 살펴본 코드를 조금 수정한다.

먼저 Developer 클래스는 다음과 같이 약간 수정하여 먹고, 자고, 코딩하는 함수를 제거하였다.

public class Developer {

    private String name;

    private int age;

    public Developer() {

        System.out.println("[default] Developer Object is created!");

    }

    public Developer(String name, int age) {

        System.out.println("[name : " + name + " age : " + age + "] Developer Object is created!");

        this.name = name;

        this.age = age;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

}

 

 

HelloWorld 클래스는 다음과 같이 수정하였다.

public class HelloWorld {

    public static void main(String[] args) {

        String name = null;

        int age = 0;

 

        Developer javaDeveloper = new Developer();

        javaDeveloper.setName("Tom");

        javaDeveloper.setAge(23);

        name = javaDeveloper.getName();

        age = javaDeveloper.getAge();

        System.out.println("name = " + name+ ", age = " + age);

 

        Developer kotlinDeveloper = new Developer("Jerry", 20);

        name = kotlinDeveloper.getName();

        age = kotlinDeveloper.getAge();

        System.out.println("name = " + name+ ", age = " + age);

    }

}

[default] Developer Object is created!

name = Tom, age = 23

[name : Jerry age : 20] Developer Object is created!

name = Jerry, age = 20

 

 

 

이제 위 코드가 실행되면서 객체가 생성될 때 실제 스택과 힙에 할당되는 값이 무엇인지 하나씩 살펴보겠다.

        String name = null;

        int age = 0;

 

 name, age는 main 함수 내에 선언된 로컬 변수이다. 로컬 변수는 스택에 저장된다고 했다. 따라서 다음과 같이 스택에 로컬 변수가 생성된다. 아직 힙에는 아무런 변화가 없다.

 

String name = null; int age = 0;

 

 다음은 Developer 객체를 생성하는 부분이다. 해당 부분을 조금씩 나눠 살펴보자. 먼저 Developer javaDeveloper 부분이 실행될 때 스택에 로컬 변수 javaDeveloper가 생성된다.

Developer javaDeveloper = new Developer();

 

Developer javaDeveloper

 

 다음으로 객체가 실제 생성되는 new Developer()로 인스턴스화가 되면서 실제 힙에 Developer 클래스의 요소들이 생성된다. 이때 생성된 힙 메모리 주소는 0x100번지라고 가정한다. 또한 함수명은 생략하고 함수라고만 표기하였다.

Developer javaDeveloper = new Developer();

 

new Developer

 객체가 기본 생성자를 통해서 만들어졌기 때문에 추가적인 작업이 없이 마무리되었다. 따라서 최종적으로 아래의 구문이 끝나게 된 것이다. 이때 스택에 있는 javaDeveloper 변수에 객체의 위치 정보인 힙의 주소가 할당된다.

Developer javaDeveloper = new Developer();

 

Developer javaDeveloper = new Developer();

 

 setter 함수를 통해서 인스턴스 변수에 값을 할당하면 힙에 해당 값이 할당된다.

javaDeveloper.setName("Tom");

javaDeveloper.setAge(23);

 

javaDeveloper.setName("Tom"); javaDeveloper.setAge(23);

 

반대로 getter 함수를 통해서 인스턴스 변수의 값을 로컬 변수에 할당할 수도 있다.

name = javaDeveloper.getName();

age = javaDeveloper.getAge();

 

name = javaDeveloper.getName(); age = javaDeveloper.getAge();

 

 코드를 보면 하나의 객체를 더 만드는데 기본 생성자가 아니라 오버로딩한 생성자를 사용했다. 이때도 로컬 변수 생성하는 단계에서는 차이점이 없다.

Developer kotlinDeveloper = new Developer("Jerry", 20);

 

Developer kotlinDeveloper

 

 다음으로 객체를 생성하는 과정도 같다.

Developer kotlinDeveloper = new Developer("Jerry", 20);

 

new Developer

 

 그리고 오버로딩된 생성자를 사용하면서 나타나는 차이점이 있다. 이 경우는 곧바로 인스턴스 변수를 생성자의 인자 값으로 초기화하기 때문에 인스턴스 변수의 값이 최종적으로 다음과 같이 된다.

Developer kotlinDeveloper = new Developer("Jerry", 20);

 

new Developer("Jerry", 20)

 

 최종적으로 해당 구문이 모두 실행되면 kotlinDeveloper에 힙 메모리 주소가 할당된다.

Developer kotlinDeveloper = new Developer("Jerry", 20);

 

Developer kotlinDeveloper = new Developer("Jerry", 20);

 

 나머지 getter, setter 함수를 사용하는 부분은 동일하다. 따라서 생략한다.

'프로그래밍 > JAVA' 카테고리의 다른 글

자바의 객체 (2)  (0) 2020.07.20
자바의 객체 (1)  (0) 2019.03.19
원형 큐(Circular Queue)  (0) 2016.12.08
DatagramSocket Example  (0) 2016.12.03
Implement Stack  (0) 2016.12.01
LinkedList Implementation  (0) 2016.11.29
How to get google server time (URLConnection Example)  (0) 2016.11.27

1. 객체 생성의 기본 형태

 객체 생성의 기본 형태는 다음과 같다.

클래스형 참조형 변수 = new 클래스형(인자);

  그리고 해당 객체의 속성과 동작, 즉 클래스의 멤버(인스턴스 변수, 함수)에 접근을 하기 위해서는 다음과 같은 형태를 가진다.

참조형 변수.인스턴스변수;
참조형 변수.함수명(인자);

 

참조형 변수?

  자바에 존재하는 8가지의 기본 데이터형을 제외한 모든 데이터형은 참조 데이터형이다. 이러한 참조 데이터형에 대한 변수를 참조형 변수라고 한다. 기본 데이터형은 boolean, byte, char, int, short, long, float, double이다. 대표적인 참조 데이터형으로는 클래스, 배열, 인터페이스 등이 있다.

이를 바탕으로 앞서 봤던 HelloWorld 클래스를 자세히 살펴보자.

public class HelloWorld {

    public static void main(String[] args) {

        System.out.println("Hello World!");

        Developer developer = new Developer();

        developer.eat();

        developer.sleep();

        developer.coding();

        Developer developer2 = new Developer();

    }

}


 클래스형(Class type)은 Developer 클래스이며 참조형 변수는 developer이다. 기본 생성자를 사용하여 별도의 파라미터가 없기 때문에 인자는 존재하지 않고 new Developer();로 객체를 생성했다.

 이때 클래스의 멤버 중 eat(), sleep(), coding() 함수에 접근하였다.

 

 그런데 인스턴스 변수에는 왜 접근하지 않았을까? 먼저 인스턴스 변수의 접근 지정자가 private라서 직접적인 접근이 불가능하다. 따라서 접근 가능한 getter, setter를 생성하여 접근하도록 한다. (접근 지정자와 캡슐화 관련해서는 별도로 정리를 해야겠다.)

 

 그래서 Developer 클래스에 getter, setter를 추가한다. 이때 name과 age를 초기화시켜줄 파라미터를 2개 가지는 생성자도 추가해주자.

public class Developer {

    private String name;

    private int age;

    public Developer() {

        System.out.println("Developer Object is created!");

    }

    public Developer(String name, int age) {

        this.name = name;

        this.age = age;

    }

    public Developer(String name, int age) {

        this.name = name;

        this.age = age;

    }

    public void eat() {

        System.out.println("eat");

    }

    public void sleep() {

        System.out.println("sleep");

    }

    public void coding() {

        System.out.println("coding");

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

}

 

 getter, setter도 결국 함수이기 때문에 접근 방식은 같다.

public class HelloWorld {

    public static void main(String[] args) {

        System.out.println("Hello World!");

        Developer developer = new Developer();

        developer.eat();

        developer.sleep();

        developer.coding();

        developer.setName("Tom");

        developer.setAge(23);

        System.out.println("name = " + developer.getName() + ", age = " + developer.getAge());

        Developer developer2 = new Developer();

    }

}

Hello World!

Developer Object is created!

eat

sleep

coding

name = Tom, age = 23

 

 developer2는 다음과 같이 추가한 생성자를 사용하여 곧바로 name과 age에 값을 할당하도록 해보자.

public class HelloWorld {

    public static void main(String[] args) {

        System.out.println("Hello World!");

        Developer developer = new Developer();

        developer.eat();

        developer.sleep();

        developer.coding();

        developer.setName("Tom");

        developer.setAge(23);

        System.out.println("name = " + developer.getName() + ", age = " + developer.getAge());

        Developer developer2 = new Developer("Jerry", 20);

        System.out.println("name = " + developer2.getName() + ", age = " + developer2.getAge());

    }

}

Hello World!

Developer Object is created!

eat

sleep

coding

name = Tom, age = 23

name = Jerry, age = 20

 

'프로그래밍 > JAVA' 카테고리의 다른 글

자바의 객체 (3)  (0) 2020.07.20
자바의 객체 (1)  (0) 2019.03.19
원형 큐(Circular Queue)  (0) 2016.12.08
DatagramSocket Example  (0) 2016.12.03
Implement Stack  (0) 2016.12.01
LinkedList Implementation  (0) 2016.11.29
How to get google server time (URLConnection Example)  (0) 2016.11.27

객체(Object)


1. 객체가 뭔가요?

 객체(Object)에 대해서 흔히 일상생활 속에서 파악할 수 있는 모든 사물이라고 비유한다. 사실 객체지향을 처음 배우면서 이런 말을 선뜻 이해하기는 쉽지 않다. 그러나 그것만큼 명확한 설명이 또 없다. (뭐라는건지...)


 그러면 예를 들어보자. 내가 정의할 객체는 개발자다. 모든 개발자는 이름이 있고 나이가 있다. 그리고 먹고, 자고, 코딩한다. 그 외에도 다양한 요소들이 있겠지만 내가 정의할 개발자라는 객체에 필요한 요소는 이게 전부라고 가정한다.


 이때 이름, 나이와 같이 객체의 특성을 표현할 수 있는 것은 '속성'이라고 하고 먹고, 자고, 코딩하는 것과 같이 움직임을 표현하는 것은 '동작'이라고 한다. 그리고 특정 객체를 구성하는 속성과 동작을 적절하게 선정하여 정의하는 것을 '객체 모델링(Object Modeling)'이라고 한다.


 앞서 속성으로 이름과 나이, 동작으로 먹고, 자고, 코딩하기를 선정한 것이 바로 객체 모델링인 것이다.


 이러한 속성과 동작을 자바에서는 인스턴스 변수와 함수로 나타내는 것이다. 그러면 실제 자바에서 개발자라는 객체를 어떤 과정을 통해서 생성하고 사용하는지 살펴보자.


2. 객체지향 개발 과정


 객체지향 개발은 다음의 3단계를 거친다.


(1) 객체 모델링

 이미 객체 모델링은 해봤다. 개발자라는 객체에 필요한 속성과 동작을 선정했다. 이러한 선정 방법에는 두 가지가 있다. 바로 일반화와 구체화 객체 모델링이다.


 '일반화 객체 모델링'은 자바 개발자, C 개발자, 파이썬 개발자로 세분화된 객체에서 일반화된 개발자라는 객체를 선정하는 것이고 반대로 '구체화 객체 모델링'은 개발자 객체에서 자바 개발자, C 개발자, 파이썬 개발자로 세분화된 객체를 선정하는 것이다.


(2) 클래스 정의하기

 개발자 객체의 속성과 동작을 선정했고 해당 요소들에 대해서 자바로 인스턴스 변수와 함수로 표현한다고 했다. 이러한 속성과 동작은 클래스에 포함된다. 즉 자바에서는 객체를 다음과 같이 클래스로 나타낸다.


public class Developer {

    private String name;

    private int age;


    public Developer() {

        System.out.println("Developer Object is created!");

    }


    public void eat() {

        System.out.println("eat");

    }


    public void sleep() {

        System.out.println("sleep");

    }


    public void coding() {

        System.out.println("coding");

    }

}


(3) 객체 생성 및 사용

 클래스를 정의한 후에 사용하려면 객체를 생성해야 한다. 객체를 생성하는 것을 '객체 인스턴스화'라고도 한다. 이러한 인스턴스화는 클래스를 실제로 메모리에 올리는 것을 의미한다.

 즉 객체가 생성되면 클래스의 구성 요소인 인스턴스 변수와 함수가 메모리에 할당되는 것이다. 이렇게 메모리에 할당된 객체를 인스턴스(instance)라고 한다. 그래서 클래스의 멤버 변수를 인스턴스 변수라고 부르는 것이다.

 또한 객체 2개를 만들면 인스턴스도 당연히 2개가 된다.


public class HelloWorld {

    public static void main(String[] args) {

        System.out.println("Hello World!");

        Developer developer1 = new Developer();

        developer1.eat();

        developer1.sleep();

        developer1.coding();


        Developer developer2 = new Developer();

    }

 }

 Hello World!

 Developer Object is created!

 eat

 sleep

 coding


'프로그래밍 > JAVA' 카테고리의 다른 글

자바의 객체 (3)  (0) 2020.07.20
자바의 객체 (2)  (0) 2020.07.20
원형 큐(Circular Queue)  (0) 2016.12.08
DatagramSocket Example  (0) 2016.12.03
Implement Stack  (0) 2016.12.01
LinkedList Implementation  (0) 2016.11.29
How to get google server time (URLConnection Example)  (0) 2016.11.27

+ Recent posts