Java

Java 문법(6) - 클래스와 객체, 접근제한자

sangchu 2022. 2. 7. 22:28
  • 클래스: 사용자가 직접 정의하여 사용할 수 있는 자료형
  • 클래스와 기본자료형
    • 차이점: 형태
    • 공통점: 형식과 사용 방법을 명시한 실체 없는 틀 → 자료형과 변수가 항상 짝꿍을 이루는 것처럼 클래스 또한 객체와 짝꿍을 이룸
  • ‘객체’는 ‘클래스’라는 자료형으로 만들어진 변수
  • 클래스는 객체가 선언되었을 때 실체를 가지게 되며, 객체를 통해 클래스에 포함된 다양한 데이터를 다룰 수 있음
  • 예시 - 붕어빵 틀과 붕어빵의 관계
    • 붕어빵 틀 없이 붕어빵이 만들어질 수 없고, 붕어빵 틀은 붕어빵을 만들지 않으면 쓸모 없는 도구가 됨
      = 클래스 없이 객체를 만들 수 없고, 클래스는 객체를 만들지 않으면 쓸모 없는 도구가 됨
    • 붕어빵 틀을 사용하기 위해 재료와 사용 메뉴얼을 필요로 하며, 만들 수 있는 붕어빵은 초코붕어빵, 슈크림붕어빵, 팥붕어빵 등 다양함
      = 클래스는 멤버 변수와 멤버 메소드로 구성될 수 있으며, 객체는 동일한 틀을 가지나 틀 안에 포함된 내용이 다를 수 있음
String str1 = "초코붕어빵";
String str2 = "슈크림붕어빵";
  • String은 java에서 기본적으로 제공하는 클래스
  • String은 클래스, str1, str2은 객체, String 클래스를 통해 str1, str2 객체를 선언했다고 해석할 수 있음. str1, str2는 동일한 클래스로 생성됐지만 각각의 내용은 다름 ⇒ 동일한 클래스로 선언된 객체들의 형식과 규칙은 동일하나 데이터 내용이 다를 수 있다

 

멤버(Member)

  • 클래스의 구성 - 멤버 변수, 멤버 메소드
    • 멤버: 클래스를 구성하는 요소 → 메소드와 변수로 이루어져 있음. 클래스는 멤버를 통해 내부 데이터를 저장하거나 연산할 수 있음
    • 멤버 변수: 클래스 내부의 변수
class ClassExample {	
	
	double mDouble;
	
	void CE_Print_mDouble() {
		System.out.println(mDouble);
	}
	
	void CE_Set_mDouble(double dInput) {
		mDouble = dInput;
	}
}
  • 위 클래스는 ClassExample이라는 이름으로 정의되고 아래와 같이 이루어져 있음
    • mDouble이라는 double형 멤버변수
    • CE_Print_mDouble라는 void형 메소드
    • CE_Set_mDouble라는 void형 메소드
  • 멤버 변수 혹은 메소드는 개수 제한 없이 필요한 만큼 선언하여 사용할 수 있음(존재하지 않아도 클래스를 만들 수 있음)
    ⇒ 이렇게 멤버들로 구성된 클래스는 하나의 자료형으로 사용할 수 있음
  • 클래스를 정의했다면 이제 객체를 통해 클래스 멤버를 사용할 수 있음(아래 코드)
import java.io.*;
class Main {
	public static void main(String[] args) {
		ClassExample ce;
		ce = new ClassExample();
		
		ce.mDouble = 10;
		ce.CE_Print_mDouble();
		
		ce.CE_Set_mDouble(30);
		ce.CE_Print_mDouble();
	}
}

class ClassExample {
	
	double mDouble;
	
	void CE_Print_mDouble() {
		System.out.println(mDouble);
	}
	
	void CE_Set_mDouble(double dInput) {
		mDouble = dInput;
	}
}
  • 4번째 줄 ClassExample ce; : ClassExamle 클래스를 자료형으로 하고 ce라는 이름을 가진 객체 선언. 하지만 이 선언만으로 객체 사용 못함
  • 참조형 자료형이므로 클래스로 만들어진 자료형 또한 new 로 메모리 할당 과정을 거쳐야 함 → 5번째 줄에서 new 를 통해 ce객체에 메모리를 할당해 줌 → ce객체는 실체를 가지게 됨
  • new 뒤에 오는 클래스이름() 부분은 ‘생성자’라고 함 → 객체에 new 로 메모리를 할당할 때 꼭 생성자 적어줘야 함
  • (String 클래스는 예외적으로 new 를 통해 메모리에 할당하는 작업 없이 바로 사용할 수 있다)
  • 7~11번째 줄은 객체를 사용하는 방법에 대한 예시 → 클래스 내부의 멤버들은 객체를 통해 제어할 수 있음
    • ce.mDouble = 10; → ce 객체 내부의 멤버 변수를 사용한 예
    • 객체 뒤에 “ . “를 붙이게 되면 객체 내부의 멤버 변수 및 메소드를 사용할 수 있음
import java.io.*;

class Main {
	public static void main(String[] args) {
		ClassExample ce1;
		ce1 = new ClassExample();

		ce1.CE_Set_mDouble(10);
		ce1.CE_Print_mDouble();

		ClassExample ce2 = new ClassExample();

		ce2.CE_Set_mDouble(30);
		ce2.CE_Print_mDouble();

	}
}

class ClassExample {

	double mDouble;

	void CE_Print_mDouble() {
		System.out.println(mDouble);
	}

	void CE_Set_mDouble(double dInput) {
		mDouble = dInput;
	}
}
  • 위 코드에서 ClassExample 클래스를 자료형으로 갖는 ce1과 ce2라는 객체 2개가 생성 됨 → 서로 아무 상관 관계가 없다 → 각 객체 내부의 멤버들은 다른 메모리 공간에 할당되기 때문

 

생성자(Constructor)

  • 일반적인 메소드는 사용자가 호출할 때에 한해 동작하지만, 생성자는 사용자가 객체를 생성할 때 자동으로 호출되는 메소드생성자는 return형을 사용하지 않으며 클래스와 동일한 이름을 가져야 함

import java.io.*;
class Main {
	public static void main(String[] args) {
		
		ClassExample ce;
		
		System.out.println("ce object Called");
		
		ce = new ClassExample();
		
		System.out.println("ce Object Created");
		
	}
}

class ClassExample {
	
	ClassExample() {
		System.out.println("Constructor Called!!!");
	}
}

// > ce object Called
//   Constructor Called!!!
//   ce Object Created
  • 위 코드는 ClassExample이라는 클래스의 생성자에 대한 예시로, 클래스 내에 매개변수를 생략한 생성자 코드를 작성함
  1. “ce object Called” 문구 출력 → ce 객체가 정상적으로 선언된 뒤 출력 코드가 실행됨
  2. “Constructor Called!!!” 문구 출력 → new 를 통해 메모리가 할당되면서 객체가 만들어짐. 객체가 만들어지는 순간 생성자가 작동하므로 저 문구가 출력됨
  3. “ce Object Created” 문구 출력
  • 위 예시처럼 매개변수가 존재하지 않는 생성자를 “기본생성자”라고 부름 → 매개변수를 포함한 생성자 또한 만들 수 있음
  • 생성자는 보통 멤버 변수들의 초기화 및 객체의 복사와 같은 역할로 사용됨

 

접근제한자

  • 접근제한자로 OOP의 4가지 특징 중 캡슐화를 가장 잘 표현할 수 있음
  • 멤버 변수 및 메소드를 선언할 때 사용
  • 멤버 변수 및 메소드를 공개하는데 있어서 제약을 걸 수 있음

import java.io.*;
class Main {
	public static void main(String[] args) {
		ClassExample ce;
		ce = new ClassExample();
		
		ce.mDouble = 10;	// 오류 발생
		ce.CE_Print_mDouble();
		
		ce.CE_Set_mDouble(30);
		ce.CE_Print_mDouble();
	}
}

class ClassExample {
	
	private double mDouble;
	
	public void CE_Print_mDouble() {
		System.out.println(mDouble);
	}
	
	public void CE_Set_mDouble(double dInput) {
		mDouble = dInput;
	}
	
}
  • 멤버 변수인 mDouble에 private, 각 메소드들에는 public 사용함
  • 7번째 줄 오류 → private형인 mDouble을 ClassExample 객체 외부에서 접근했기 때문
  • private 접근제한자는 객체 자기 자신 안에서만 사용할 수 있도록 제한하는 구문이므로 객체 바깥에서 멤버에 직접 접근을 시도하면 오류가 발생
  • private형의 접근제한자를 가진 멤버에 접근하고 싶다면 public으로 선언된 멤버를 활용해야 함
import java.io.*;
class Main {
	public static void main(String[] args) {
		ClassExample ce;
		ce = new ClassExample();
		
		ce.CE_Set_mDouble(30);
		ce.CE_Print_mDouble();
	}
}

class ClassExample {
	
	private double mDouble;
	
	public void CE_Print_mDouble() {
		System.out.println(mDouble);
	}
	
	public void CE_Set_mDouble(double dInput) {
		mDouble = dInput;
	}
	
}
  • private 및 public을 통해 외부에서 접근 가능한 멤버를 설정해 줄 수 있고, 이는 프로그래머로 하여금 정보 은닉 효과 및 중요 정보의 보안성을 높여주는 방법으로 사용됨

 

static에 대하여

  • 이전에 main 메소드에는 무조건 static 이 붙어야 한다고 설명함. 이는 메소드 혹은 변수에 붙여 사용할 수 있는데 이를 클래스에서 유용하게 사용할 수 있음
  • 만약 클래스 안의 멤버에 static 이 붙으면 그 멤버는 클래스의 객체를 선언하지 않고 바로 콜해서 사용할 수 있음
import java.io.*;
class Main {
	public static void main(String[] args) {
		
		ClassExample.mInt = 3;
		ClassExample.Print();
		
		ClassExample c = new ClassExample();		
		c.mInt = 20;
		c.Print();
	}
}

class ClassExample {
	
	public static int mInt;
	
	public static void Print() {
		System.out.println( mInt );
	}
	
}

// > 3
//   20
  • 5, 6번째 줄 static이 붙은 mInt변수와 Print메소드를 객체 선언 없이 직접 사용함 → 객체에 메모리를 할당하지 않고 사용할 수 있는 것 처럼 보이지만, 사실 static 이 붙은 멤버들은 프로그램이 시작될 때 우선 메모리에 할당되기 때문에 new 를 통한 객체 초기화가 필요 없음
  • main 메소드에 static 이 붙어야 하는 이유는 main 메소드가 프로그램이 처음 시작되는 메소드이기 때문.
  • main 메소드보다 빨리 실행될 수 있는 코드가 없기 때문에 static을 사용하지 않으면 main 메소드의 메모리를 할당해줄 부분이 존재하지 않음. 때문에 프로그램 시작과 함께 main 메소드의 메모리를 할당해야 함
  • static 을 사용할 때 클래스 내에서 static 을 사용하는 메소드는 멤버변수 사용시 static 멤버변수만 사용가능하다는 점 주의
class ClassExample {
	
	public int mInt;
	
	public static void Print() {
		System.out.println( mInt );
	}
}
  • 앞서 사용한 ClassExample 클래스의 mInt에 있던 static 을 제거하면 컴파일 진행시 오류가 발생 → Print 메소드에 static 이 사용되었지만 mInt 변수에는 static 이 사용되지 않았기 때문에 발생하는 오류

 

 

 

 

 

'바로 실행해보면서 배우는 java'를 학습하며 정리한 문서