본문 바로가기

Java/기본 이론

[JAVA] Chapter 16. 클래스의 구성과 선언

1. 클래스의 구성 요소

자바에서 클래스는 멤버(member)로 속성을 표현하는 필드(field)와 기능을 표현하는 메소드(method)를 가진다.

또한, 경우에 따라 클래스는 생성된 객체의 필드를 초기화해주는 메소드인 생성자(constructor)를 가진다.

 

class Bungerbbag {                    // 클래스 이름

    private String hiddenmenu;  // 필드
   	public String flavor;    // 필드

 

    Bungerbbang(int amount, String flavor) { // 생성자

        this.amount = 6;
        this.flavor = 슈크림;

    }

    public String buyBungerbbang() { // 메소드
        return this.amount + "개, " + this.flavor + " 맛 ";
        
    }

}

 

1.1. 필드(field)

클래스의 필드(field)란 클래스에 포함된 변수(variable)를 의미한다.

클래스 내에서 필드는 선언된 위치에 따라 클래스 변수, 인스턴스 변수, 지역 변수로 나뉜다.

 

선언된 위치를 스코프라고 하는데, 스코프에 따라 나뉘는 변수는 각기 다른 유효 범위를 가진다.

이는 추후 Chapter 18에서 자세히 다룰 것이다. 

 

1.2. 메소드(method)

클래스에서 메소드(method)란 어떠한 특정 작업을 수행하기 위한 명령문의 집합을 말한다.

메소드를 이용하면 길게 작성된 코드를 줄일 수도 있고, 원하는 기능을 구체적으로 설정하는 알고리즘을 구성할 수 있다. 

또한, 모듈화로 인해 전체적인 코드의 가독성이 좋아진다.

코드의 유지보수를 비롯한 협업에서 '가독성'의 중요함은 여러번 강조해도 지나침이 없다. 

메소드의 가장 큰 장점은 기능을 정의하는 것인데, 이 기능을 정의하는 동작을 여러 클래스가 공유할 수 있다.

때문에 프로그램에 문제가 발생하거나 기능의 변경이 필요할 때 손쉽게 유지보수를 할 수 있다.

 

1.3. 생성자(constructor)

클래스를 가지고 객체를 생성하면, 메모리에 해당 객체의 데이터 공간이 즉시 할당된다.

하지만 이렇게 생성된 객체는 모든 인스턴스 변수가 아직 초기화되지 않은 상태이다. 따라서 자바에서는 객체의 생성과 동시에 인스턴스 변수를 원하는 값으로 초기화할 수 있는 생성자(constructor)라는 메소드를 제공한다. 



자바에서 생성자(constructor)의 이름은 해당 클래스의 이름과 같아야 한다.만약 Bungerbbang이라는 클래스의 생성자를 사용하고 싶다면 Bungerbbang()이라고 선언하면 된다. 

 

 

생성자가 필요한 순간은 알고리즘을 여러번 사용할 경우이다. 

알고리즘 연산을 순차적으로 진행할 때, 특정 클래스의 데이터가 변경되었다면 알고리즘의 구동 결과가 다르게 나타난다.

 

생성자는 이러한 문제를 사전에 방지하고 프로그램이 정상적으로 작동하도록 돕는 기능을 한다. 

 

2. 클래스의 선언

클래스는 객체를 구성하는 설계도이다. 추상적인 개념의 객체라는 정보를 구체적으로 표현한 것이다. 

자바는 개발자의 편의를 위해 유용하게 사용할 수 있는 많은 수의 클래스를 이미 정의하고 있다. 
또한, 개발자는 자신이 원하는 동작을 수행하는 새로운 클래스를 만들어 낼 수도 있다. 

자바에서 클래스를 선언하는 방법은 접근 제어자와 함께 class 키워드를 사용하는 것이다. 

접근제어자 class 클래스이름{ 필드 및 메소드 }

 

 슈크림을 넣다 할때의 Put in 이다. 푸틴이 아니다.

 

접근 제어자는 정보 은닉을 위한 키워드로, 접근 제어자의 등급에 따라 클래스에 접근할 수 있는 권한이 설정된다. 

 

public 멤버는 모든 객체에서 접근이 가능하지만, priviate 멤버는 해당 객체 내의 변수나 메소드만이 접근할 수 있다. 

쉽게말해, 권한의 설정에 따라 멤버에 접근할 수 있는 길에 검문소가 세워지는 것과 같다.

통행증이 없는 사람은 이 검문소를 지나갈 수 없는 것이다. 

 

3. 인스턴스의 생성

인스턴스는 현재 실행하는 클래스를 통해 객체를 생성할 때, 메모리에 할당되는 것을 말한다.

말이 어렵지만, 특정 Method에서 다른 클래스의 구조를 가져올 때, 진행하는 변수 선언인 것이다. 

 

public class BbangStore{

	public static void main(String[] args){
    
    	Bbang bunger;	//인스턴스 선언
        bunger = new Bbang();	//인스턴스 생성
        
        bunger.name = "슈크림 붕어빵";	//클래스에 이미 생성된 멤버를 bunger 객체에 변수선언
        bunger.flavor = "슈크림";	
        bunger.amount = 3;
        bunger.price = 1000; 
    	
        bunger.bake("반죽", "슈크림");	//클래스에 이미 생성된 메소드에 접근
    }
} 

class Bbang{	//클래스 생성
    
	String name;
	String flavor;
	int amount;
	int price; 
        
	String bake(String in1, String in2){
        	
		String bake = "굽다";
		String Bbang = bake + in1 + in2;
 
		return Bbang;
	}
}

우선 인스턴스를 생성하기 위해서는 클래스 이름 객체참조변수이름; 으로 선언해야 한다. 

이후 new 명령어를 이용하여 '인스턴스'를 생성하고 인스턴스 주소를 이용해 변수를 선언한다. 

 

이렇게 선언된 인스턴스는 참조형 변수와 같고, Stack에 저장된 참조 주소를 바탕으로 heap 메모리에 접근한다. 

 

bunger.name = "슈크림 붕어빵"

 

이를 직역하자면, 다음과 같다.

 

  • 이미 인스턴스로 생성된 객체 bunger 안에 name이라는 변수를 '선언'하는데, 이 데이터는 "슈크림 붕어빵"이다. 

여기서 데이터 타입은 이미 class로 생성된 Bbang과 정확하게 일치한다.

 

클래스를 이용하면 동일하게 정제된 다양한 객체를 생성할 수 있다. 

예시 코드를 예로하자면 '붕어빵'만이 아니라 '피자빵'도 만들수 있고, '계란빵'도 만들수 있다는 것이다.

 

4. 클래스의 객체 배열 

package make20210430;

public class Ex1 {

	public static void main(String[] args) {

		CreditCard[] consumer = new CreditCard[5];
		consumer[0] = new CreditCard();
		consumer[0].owner = "둘리";
		consumer[0].number = 200;
		consumer[0].Print();
		
		consumer[1] = new CreditCard();
		consumer[1].owner = "길동";
        consumer[1].number = 1000000000;
        consumer[1].Print();
		System.out.println(consumer[1].owner);
        
        ...
	}

}

class CreditCard{
	
	long number;
	String owner;
	
	void Print() {
		if(number>100000) 
		{
			System.out.println(owner+"의 신용카드 잔액은 "+number+" 원 입니다.");
		}
		else 
		{
			System.out.println(owner+"의 가난한 신용카드 잔액은 "+number+" 원 입니다.");
		}
	}
}

 

클래스는 객체 배열로 선언할 수 있다. 

객체 배열로 선언하는 경우, 데이터 타입에 배열 형태를 넣고, 해당 class의 heap을 얼마나 할당할지 공간을 선언해야 한다.

다만 주의할 것은 class는 이미 객체 상태로 데이터 타입 참조형태인 점이다.

 

쉽게 말해, CreditCard[] consumer = new CreditCard[5]; 로 class의 배열을 선언하면, 각 배열에 '참조값'이 할당된다.

consumer[0]에 '참조값'이 할당된 상태이기 때문에, 해당 데이터 영역에서는 별도의 값을 '할당'할 수 없다. 

데이터를 가르키는 공간이 할당된 상태이기 때문이다.

즉, 배열로 선언한 경우에 해당 배열에 해당하는 heap 데이터를 재차 생성해줘야한다는 것이다. 

 

이에 consumer[0]에 대해 new 로 heap 데이터를 재차 할당하고, 데이터 공간이 생긴 후에야 직접 데이터를 집어넣을 수 있다. 

기본적인 용법이지만 프로그램을 짜다가 한번쯤은 부딪칠 수 있는 문제이다. 반드시 기억해두자.