Java Object Oriented Programming(Variable & Method)

Variable & Method

java

참고서적 : Java의정석 3rd Edition

변수(Variable) and Method

Variable은 Class Variable, Instance Variable, Local Variable 3가지의 종류가 있다.
Class 내부에 생성되는 Member Variable을 제외한 나머지 Variable은 모두 Local Variable이며, Member Variable중 static이 붙은 것은 Class Variable

Class Variable(Method area 영역에서 생성) = static Member Variable
Instance Variable(heap 영역에서 생성) = Member Variable
Local Variable = Member Variable를 제외한 나머지 Variable

Member Variable은 Class내부에 선언한 Property들을 나타낸다.

Variable 종류 선언 위치 생성시기
Class Variable Class 영역 Class가 메모리에 올라갈 때
Instance Variable Class 영역 Instance가 생성될 때
Local Variable Class 영역 이외의 영역 Variable 선언문이 수행되었을 때
1
2
3
4
5
6
7
8
9
10
class Variable {
// Class 영역
int iv; // Instance Variable
static int cv; // Class Variable

void method() {
// Method 영역
int lv = 0; // Local Variable
}
}

Instance Variable : 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다.
Class Variable : 공통된 저장공간을 공유하게 된다. 그래서 서로 같은 값을 가진다.

  • Instance를 생성하지 않고도 언제라도 바로 사용할 수 있다.
    Local Variable : Method내에서 선언되어 Method내에서만 사용 가능하다.

Class Variable은 Class가 메모리에 Loading될 때 생성되어 프로그램이 종료될 때 까지 유지되며 public을 붙이면 Global Variable의 성격을 가진다.

Class Variable & Instance Variable

Class Variable : 전체적으로 한번에 관리할 값
Instance Variable : 개인적으로 관리할 값

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
29
30
31
32
33

public class CardTest {
public static void main(String[] args) {
Card c1 = new Card();
c1.kind = "Heart";
c1.num = 7;

Card c2 = new Card();
c2.kind = "Spade";
c2.num = 4;

System.out.println("c1은 "+c1.kind+", "+c1.num+"이며, 크기는 ("+c1.width+", " +c1.height+")");
System.out.println("c2은 "+c2.kind+", "+c2.num+"이며, 크기는 ("+c2.width+", "+c2.height+")");

System.out.println("c1의 width, height의 크기를 75, 125 으로 변경합니다.");
c1.width = 75;
c1.height = 125;
// Card.width = 75 이것이 더 명시적이다.
// Card.heigth = 75 이것이 더 명시적이다.

System.out.println("c1은 "+c1.kind+", "+c1.num+"이며, 크기는 ("+c1.width+", " +c1.height+")");
System.out.println("c2은 "+c2.kind+", "+c2.num+"이며, 크기는 ("+c2.width+", "+c2.height+")");
// c1만 변경했는데 c2 width, height도 변경되었다.
}
}

class Card {
String kind;
int num;

static int width = 150;
static int height = 250;
}

Instance Variable은 Instance가 생성될 때 마다 생성되므로 Instance마다 각기 다른 값을 유지할 수 있지만, Class Variable은 모든 Instance가 하나의 저장공간을 공유하므로 항상 공통된 값을 가진다.

Method

Method의 장점

  1. 높은 재사용성(reusability)
  2. 중복제거 : 중복코드를 하나의 Method로 작성하기에 코드를 수정할때도 편하다.
  3. 프로그램의 구조화 : Main Method안에를 단순화 하고 구현해야할 Method들을 미리 선언만 해둔다.

Method의 선언과 구현

Method는 선언부, 구현부로 구성되어있다.

Method 선언부
Method 이름, Method 선언, Return type으로 구성되어 있다.

1
2
3
4
public int add(int x, int y) {
int result = x+y;
return result;
}

add Method는 x, y 2개의 int형 입력받아서 x+y인 int를 return한다.

Parameter 선언
Parameter는 Method에 들어가 개수를 ,를 이용하여 선언하며 선언 개수는 제한이없지만 Parameter가 많다면 배열이나 참조변수를 사용하는 것이 좋다.

Return type
Method가 특정 작업을 마치고 return해주는 값을 나타내며 Method에서 선언한 return type을 반드시 지켜줘야하며 만약 반환겂이 없다면 void를 적어줘야한다.

Local Variable
Method 내에 선언된 변수들은 그 Method 내에서만 사용할 수 있다.

Method 호출

Method를 사용하기 위해서는 Method 호출을 해야한다.

1
2
3
4
5
MethodName(argument1, arg2 ...); // Method 호출방법

printAll(); // void type을 호출 하는방법.
int result = add(3,5) // parameter 2개를 가지는 add method 호출방법.

Argument : Method를 호출할 때 괄호 안에 지정해준 값, Argument는 Method의 parmeter의 개수와 일치해야한다.(type 일치여부는 당연한 것이다!)

return

return문은 void type일 경우를 제외하고는 실행중인 Method를 종료하고 호출한 Method로 돌아가는 것을 나타낸다.

void는 Compiler가 자동으로 마지막에 return;을 해주기 때문이다.

1
2
3
int abs(int x) {
return x >= 0 ? x : -x; // x>=0 크다면 x를, 작다면 -x를 반환한다.
}

Developer는 호출하는 쪽에서의 잘못된 부분을 호출하는 경우를 고민해서 그 경우를 대비해야한다, 즉 Argument에 대하여 유효성을 검사해야한다.

Divide를 하는 Method같은 경우 0으로 나눌경우 문제가 발생하기 때문에 입력받은 argument값이 0인지를 판단하여 Error를 발생해줘야한다.

1
2
3
4
5
class float divide(int x, int y) {
if( y == 0) { return 0; }

return x / (float)y;
}

JVM Memory Structure

응용프로그램이 실행되면, JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고 JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.

ex) Method area, call stack, heap

Method area : 프로그램 실행 중 어떤 클래스가 사용되면, JVM은 해당 클래스의 클래스파일(*.class)을 읽어서 분석하여 클래스에 대한 정보(클래스 데이터)를 이곳에 저장한다. 이 때, 그 클래스의 Class Variable도 이 영역에 함께 생성된다.

heap : Instance가 생성되는 공간, 프로그램 실행 중 생성되는 모든 Instance Variable은 heap 영역에서 생성된다.

call stack : Method의 작업에 필요한 메모리 공간을 제공한다. Method가 작업을 수행하는 동안 Local Variable들과 연산의 중간결과 등을 저장하는데 사용된다.

call stack의 제일 상위에 위치하는 Method가 현재 실행 중인 Method이며 나머지는 대기상태에 있게 된다.

call stack의 특징

  • Method가 call되면 수행에 필요한 만큼의 메모리를 stack에 할당 받는다.
  • Method가 수행을 마치고나면 사용했던 메모리를 반환하고 stack에서 제거된다.
  • Call Stack의 제일 위에 있는 Method가 현재 실행 중인 Method이다.
  • 아래에 있는 Method가 바로 위의 Method를 호출한 Method이다.

call stack의 작동 순서를 확인해 본다.

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
29
package chapter06;

public class CallStackTest {
public static void main(String[] args) {
System.out.println("main start");
firstMethod();
System.out.println("main end");
}

static void firstMethod() {
System.out.println("fistMethod start");
secondMethod();
System.out.println("fistMethod end");
}

static void secondMethod() {
System.out.println("secondMethod start");
System.out.println("secondMethod end");
}
}

// 결과 값

main start
fistMethod start
secondMethod start
secondMethod end
fistMethod end
main end

기본형 argument와 참조형 argument

Argument의 type이 기본형인 경우 값이 복사되지만, type이 참조형인 경우는 Instance의 주소가 복사된다.

기본형 argument : 변수의 값을 읽기만 할 수 있다.(read only)

참조형 argument : 변수의 값을 읽고 변경할 수 있다. (read & write)

아래는 기본형 argument에 대한 예시이다.

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

public class PrimitiveParamEx {

public static void main(String[] args) {
Data d = new Data();
d.x = 10;
System.out.println("Main => x : "+ d.x);

change(d.x);
System.out.println("after change => x : "+ d.x);
}

static void change(int x) {
x = 1000;
System.out.println("change => x : " + x);
}
}

class Data {int x;}

// 결과 값
Main => x : 10
change => x : 1000
after change => x : 10

d.x의 값이 변경된것이 아닌 change의 x의 값이 변경된 것이다.

원본이 아닌 복사본이 변경된 것이라 원본에는 아무런 영향을 미치지 못한다.

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
29
30
31
32
package chapter06;

class Data2 {
int x;
}

public class ReferenceParamEx {

public static void main(String[] args) {
Data2 d = new Data2();
d.x = 20;
System.out.println("main() : x => "+d.x);

change(d);
System.out.println("After change(d)");
System.out.println("main() : x =>" + d.x);


}

static void change(Data2 d) {
d.x = 2000;
System.out.println("change : x => "+d.x);
}
}

// 결과 값
main() : x => 20
change : x => 2000
After change(d)
main() : x =>2000

이전과 달리 값이 변경이 되었는데 그 이유는 change가 Data2자체를 parameter로 받고 있기 때문에 reference형이 되었기 때문이다.
즉 값이 저장된 주소를 넘겨주어서 변경이 되기 때문이다.
아래에 java의 자료형에 대하여 정리를 해두었다.

JAVA의 자료형

기본 자료형

  • char, byte, short, int, long, float, double, boolean
  • 기본 자료형으로 선언된 변수에는 실제 값이 저장된다.
  • Pass by Value

참조 자료형

  • Class, Interface, Array
  • 참조 자료형으로 선언된 변수에는 Instance에 대한 주소값이 저장된다.
  • Pass by Reference

기본 자료형 종류

  • 논리형 boolean 1bit
  • 문자형 char 16bit, byte 8bit, short 16bit
  • 정수형 short 16bit, int 32bit, long 64bit, float 32bit
  • 실수형 float 32bit, double 64bit

참조 자료형 종류

  • Class : Class로 부터 생성된 객체(instance)의 시작 주소값을 가진다.
  • Array : Java에서는 배열을 Class로 취급하기 때문에 생성된 배열의 시작 주소값을 가진다.
  • Interface : Interface를 구현한 Class의 Instance 시작 주소값을 가진다.

아래는 Parameter의 Arrays를 넣은 값이다.

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
29
30
31
32
33
34
import java.util.Arrays;

public class ReferenceParamEx3 {

public static void main(String[] args) {
int[] arr = { 3, 2, 1, 6, 5, 3 };

printArr(arr);
sortArr(arr);
}

static void printArr(int[] arr) {
for (int i = 0; i < arr.length; i++) {
if(i != arr.length-1) {
System.out.print(arr[i]+" ,");
}else {
System.out.println(arr[i]);
}
}
}

static void sortArr(int[] arr) {

Arrays.sort(arr);

for (int i = 0; i < arr.length; i++) {
if(i != arr.length-1) {
System.out.print(arr[i]+" ,");
}else {
System.out.println(arr[i]);
}
}
}
}

참조형 반환타입

Parameter뿐만이 아니라 return value도 참조형이 될 수 있다.

1
Data d2 = copy(d);
Share