본문 바로가기

프로그래밍/Java

Java_객체지향언어(2)_인스턴스변수, 클래스변수, 지역변수, 메서드 사용법, 기본형 매개변수와 참조형 매개변수의 차이

① 선언위치에 따른 변수의 종류

class Variables
{
    int iv;	        //인스턴스 변수
    static int cv;	//클래스 변수(static 변수)
    
    void method()
    {
    	int lv=0;	//지역변수
    }
}

- 인스턴스 변수 (iv)
: 인스턴스마다 고유한 상태를 유지해야하는 속성의 경우, 인스턴스 변수로 선언한다.
- 클래스 변수 (cv)
: 인스턴스마다 공통적인 값을 유지해야하는 속성의 경우, 클래스 변수로 선언한다.
클래스 변수는 인스턴스 변수와 달리 인스턴스를 생성하지 않고 언제든지 바로 사용할 수 있다. '클래스이름.클래스 변수'
- 지역 변수 (lv)
: 메서드 내에서만 선언되어 메서드 내에서만 사용 가능하다. 메서드가 종료되면 소멸되어 사용할 수 없게 된다.

ex) 클래스 변수와 인스턴스 변수

class Card {
    String kind;    
    int number;		//인스턴스 변수, 개별 속성
    
    static int width = 100;		
    static int height = 250; 	//클래스 변수, 공통 속성
}
public class Ex6_3 {

	public static void main(String[] args) {
		System.out.println("Card.width="+Card.width);
		System.out.println("Card.height="+Card.height);
		
		Card c1=new Card();
		c1.kind="Heart";
		c1.number=7;
		
		Card c2=new Card();
		c2.kind="Spade";
		c2.number=4;
		
		System.out.println("c1은 "+c1.kind+", "+c1.number
				+"이며, 크기는("+c1.width+","+c1.height+")");
		System.out.println("c2은 "+c2.kind+", "+c2.number
				+"이며, 크기는("+c2.width+","+c2.height+")");
		System.out.println("c1의 width와 height를 각각 50, 80으로 변경합니다.");
		c1.width=50;
		c1.height=80;
		
		System.out.println("c1은 "+c1.kind+", "+c1.number
				+"이며, 크기는("+c1.width+","+c1.height+")");
		System.out.println("c2은 "+c2.kind+", "+c2.number
				+"이며, 크기는("+c2.width+","+c2.height+")");
	}

}

class Card{
	String kind;
	int number;
	static int width=100;
	static int height=250;
}
결과
Card.width=100
Card.height=250
c1은 Heart, 7이며, 크기는(100,250)
c2은 Spade, 4이며, 크기는(100,250)
c1의 width와 height를 각각 50, 80으로 변경합니다.
c1은 Heart, 7이며, 크기는(50,80)
c2은 Spade, 4이며, 크기는(50,80)

=> 클래스 변수의 값을 변경할 땐 예제의 c1.width = 50; c1.height = 80; 대신 Card.width = 50; Card.height = 80; 과 같이 클래스 이름으로 사용하는 것이 알아보기 쉽다.


② 메서드란 ?
: 특정 작업을 수행하는 문장들을 묶어서 이름을 붙인 것이다.
- 다음과 같은 형식으로 메서드를 정의한다.

반환타입 메서드이름 (타입 변수명, 타입 변수명, ...)
{
	//메서드 호출시 수행될 코드
}



③ 메서드의 선언부
: 메서드의 선언부는 '메서드 이름'과 '매개변수 선언(입력)', '반환 타입(출력)'으로 구성되어 있다.

int add(int x, int y) {		//반환타입 메서드 이름(매개변수선언1, 매개변수선언2)
    int result = x + y; 
    
    return result;			//결과 반환
}

- 매개변수 선언
: 메서드가 작업을 수행하는데 필요한 값들(입력)을 제공받기 위한 것이다.
일반적인 변수선언과 달리 두 변수의 타입이 같아도 변수의 타입을 생략할 수 없다.
- 반환타입
: 반환값의 데이터 적는다. 반환값이 없는 경우 'void'를 적어야 한다.


④ 메서드의 구현부
: 메서드의 괄호{}를 메서드의 구현부라고 하는데, 메서드를 호출했을 때 수행될 문장들을 넣는다.

- return문
: 메서드의 반환타입이 'void'가 아닌 경우, 구현부{} 안에 'return 반환값;'이 반드시 포함되어 있어야 한다.
이 값의 타입은 반환타입과 일치하거나 자동형변환이 가능한 것이어야 한다.
- 지역변수
: 메서드 내에 선언된 변수를 지역변수라고 한다. 서로 다른 메서드라면 같은 이름의 변수를 선언해도 된다.


⑤ 메서드의 호출
- 메서드를 호출할 때 괄호 ()안에 지정해준 값들을 '인수' 또는 '인자'라고 하는데,
인자의 개수와 순서는 호출된 메서드에 선언된 매개변수와 일치해야 한다.


⑥ 메서드의 실행 흐름

class Ex6_4 {
    public static void main(String[] args) {
    	MyMath mm = new MyMath();	// 실행 순서2. 객체 생성
        long result1 = mm.add(5L, 3L);
        long result2 = mm.subtract(5L, 3L);
        long result3 = mm.multiply(5L, 3L);
        dougle result4 = mm.divide(5L, 3L);	// 실행 순서3. 객체 사용(객체의 메서드 호출)
        
        System.out.println("add(5L, 3L) = "+result1);
        System.out.println("subtract(5L, 3L) = "+result2);
        System.out.println("multiply(5L, 3L) = "+result3);
        System.out.println("divide(5L, 3L) = "+result4);
    }
}

class MyMath {	// 실행 순서1. 클래스 작성 (메서드 작성) 메서드는 클래스 영역내에서만
	long add(long a, long b) {
    	long result = a + b; 
        return result;	//두 줄을 return a+b;로 간단히 할 수 있다. 
    }
    long subtract(long a, long b) {return a-b;}
    long multiply(long a, long b) {return a*b;}
    double divide(double a, double b) {
    	return a/b;
    }
}

=> 실행흐름
1. MyMath 클래스 작성(메서드 작성) → 2. MyMath 객체 생성 → 3. MyMath 객체 사용(객체의 메서드 호출) → 작업을 마치면 호출한 곳으로 돌아온다.


기본형 매개변수
: 매개변수의 타입이 기본형일 때는 기본형 값이 복사되지만, 참조형일 때는 인스턴스의 주소가 복사된다.
- 기본형 매개변수 → 변수의 값을 읽기만 할 수 있다.
참조형 매개변수 → 변수의 값을 읽고 변경할 수 있다.

class Data { int x; }

class Ex6_6 {
    public static void main(String[] args) {
    	Data d = new Data();	//실행흐름1. 객체생성
        d.x=10;		//실행흐름2. d.x에 10을 저장
        System.out.println("main() : x = " +d.x);	//실행흐름3. main() : x= 10으로 출력
        
        change(d.x)	//실행흐름4. change(d.x)가 메서드 호출 
        System.out.println("After change(d.x)");	//실행흐름8. After change(d.x)로 출력
        System.out.println("main() : x = "+d.x);	//실행흐름9. maint() : x = 10으로 출력
    }
    
    static void change(int x) {	//실행흐름5. 기본형 매개변수이므로 int x에 10이 저장됨.
    	x = 1000;	//실행흐름6. 지역변수 x에 1000이 저장
        System.out.println("change() : x = "+x);	//실행흐름7. change() : x = 1000으로 출력
    }
}
결과
main() : x = 10
change() : x = 1000
After change(d.x)
main() : x = 10

=> 기본형 매개변수로 호출해서 'd.x'의 값이 변경된 것이 아니라 chang메서드의 매개변수 x의 값이 변경된 것이다.
class Data에 선언된 인스턴스변수 x와 메서드 내에 기본형으로 선언된 지역변수 x는 서로 다른 저장공간이기 때문에 값이 변경되지 않는다.


참조형 매개변수

class Data2 { int x; }

class Ex6_7 {
    public static void main(String[] args) {
    	Data2 d = new Data2();	//실행흐름1. 객체 생성
        d.x = 10;	//실행흐름2. d.x에 10저장
        System.out.println("main() : x = "+d.x);	//실행흐름3. main() : x = 10으로 출력
        
        change(d);	//실행흐름4. change(d)가 메서드를 호출함
        System.out.println("After change(d)");	//실행흐름 8. After change(d)로 출력
        System.out.println("main() : x = "+d.x);	//실행흐름 9. main() : x = 1000으로 출력
    }
    
    //실행흐름5. 참조형 매개변수이므로 main()의 주소값이 change()에 복사됨.
    static void change(Data2 d) {
    	d.x=1000;	//실행흐름6. d.x에 1000이 저장됨. 
        System.out.println("change() : x = "+d.x);	//실행흐름7. change() : x = 1000으로 출력
    }
}
결과
main() : x = 10
change() : x = 1000
After change(d)
main() : x = 1000

=> class Data2에 선언된 인스턴스 변수 x와 메서드 내에 참조형으로 선언된 지역변수 x는 참조형 변수이므로 주소를 복사하기 때문에 같은 저장공간이므로 값이 변경된다.