자바 - 클래스와 인스턴스
- 8 minsJava - Class & Instance:
Class?
- 추상적인 객체를 프로그래밍 언어로 구체화 시켜놓은 형태
Method?
- 개발자가 특정한 행동을 정의한 후, 그 행동을 호출하면 프로그램에서 그대로 실행하는 것을 의미
- 클래스 기반 언어에서 클래스 내부에 정의.
- 메서드는 프로그램이 실행되고 있을 때 클래스에서 생성된 인스턴스와 관련된 동작을 정의.
- 메서드는 런타임 중에 클래스 인스턴스 (또는 클래스 객체)에 저장되어 있는 데이터에 접근할 수 있는 특수 속성을 가지고 있음
**메서드 선언 방법**
public static 리턴타입(자료형, void) 메서드명() {
메서드 작성
return 리턴 데이터;
}
//리턴타입에는 int, string, boolean 등의 자료형을 넣어줍니다
//리턴타입에 void가 들어가는 경우 return받는 데이터가 없다는 것을 의미합니다
//리턴받는 자료형이 있다면 메서드의 마지막에 return 리턴데이터를 입력해줍니다
//메소드의 리턴타입과 같은 자료형으로만 return을 받을 수 있습니다
//리턴타입이 void라면 return을 할 필요가 없습니다
System.out.println("Hello");
/* println("Hello"); 실제 작업 수행 명령
*System.out = 피연산자
=> JVM 기본 출력 장치의 정보가 들어있는 메모리의 주소
*JVM 기본 출력 장치 = 터미널
*println = method = 연산자 = (message)
*("Hello") = argument = 피연산자 = (parameter)
*/
**메서드 실행 (호출)**
예제)
Scanner KeyIn = new Scanner(Sstem.in);
KeyIn.nextLine();
// KeyIn : 레퍼런스 = 정보가 들어있는 메모리의 주소 = Scanner 객체
// KeyIn 변수에 scanner 정보가 들어있는 것은 아니지만 정보가 들어있는 변수로 간주하여 표현함.
// -> 의사소통을 단순하게 하기 위해 & 이해를 쉽게 하기 위해
// nextLine() : 레퍼런스에 적혀있는 주소를 찾아가서 그 메모리의 저장된 정보를 이용하여 작업을 수행
// => "KeyIn 객체에 대해 nextLine()을 호출"
// => 스캐너 객체를 가지고 넥스트라인 메서드를 호출 가능
/*
용어 정리
- Instance : 정보가 담겨있는 메모리
public class Method_Parameter {
public static void main(String[] args) {
String name = "javabeginnerstutorial.com";
int age = 10;
JBT instance = new JBT();
instance.method(name, age);
}
}
class JBT {
void method(String parameter1, int parameter2) {
System.out.println("1st Parameter :" + parameter1 + " , 2nd Parameter : " + parameter2);
}
}
**<call by value>**
-> **메서드를 호출할 때, 값을 넘긴다**
// => 아규먼트가 primitive data type인 경우,
// 메서드를 호출할 때 값을 넘긴다.
// => 자바에서는 primitive data type에 대해서
// 메모리(변수) 주소를 넘기는 방법이 없다.
//
main() {
int a = 100;
int b = 200;
swap(a,b)
}
swap(int a, int b) {
int temp = a;
a = b;
b = temp:
}
**<stack>**
-> 메서드의 로컬변수를 만드는 메모리
main()이 호출되는 순간 main()이 사용할
로컬 변수 생성 (call by value)
swap()이 사용할 로컬 변수 생성
**<Heap>**
-> new 명령으로 만드는 메모리
(call by reference)
- Primitive data type을 제외한 모든 변수 → 주소를 저장하는 변수
Instance?
- 메서드는 호출이 되기 위해서 클래스로부터 객체를 생성해야 하는데 생성된 객체를 인스턴스라고 함 = 선언한 클래스를 이용해서 프로그램 내에서 실체화 시킨 것
- 인스턴스는 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다.
클래스 & 인스턴스 활용 예제
public class Human {
//필드(멤버 변수)
public String name; // 이름 필드(변수)
public String birth; // 생일정보 필드
public char bloodType; // 혈액형 필드
public char sex; // 성별 필드
public String job; // 직업 필드
public int height; // 키 필드
public int weight; // 몸무게 필드
public Human() {} // Human 클래스의 생성자
//메소드(멤버 함수)
public void getName(){
System.out.println("이 사람의 이름은 " + name + "입니다.");
} // 이름을 출력하는 메소드
public void getBloodType() {
System.out.println("이 사람의 혈액형은 " + bloodType + "형 입니다");
} // 혈액형을 출력하는 메소드
public void getJob(){
System.out.println("이 사람의 직업은 " + job + "입니다.");
} // 직업을 출력하는 메소드
}
클래스 선언
이 코드는 위에서 예시로 든 사람이라는 객체를 클래스로 구현한 것이다. 코드를 크게 뜯어서 분석해보면 먼저 public class Human
이라는 코드로 클래스의 정의를 시작하고 {}
안에 필요한 내용을 구현한다. 필요한 내용이라 함은 필드와 메소드를 말할 수 있다.
필드와 메소드
자바에서는 클래스 내부의 멤버 변수를 필드라고 하고 멤버 함수를 메소드라고 칭한다. 위 코드에 주석에서 설명했 듯이 코드와 같이 작성할 수 있다. 이들은 클래스의 내부에 구현되며 절대 클래스 외부에 작성될 수 없다. 바로 앞에서 언급했던 “캡슐화”라는 개념 때문이다.
public, 접근 지정자
class Human
이나 String name
과 같은 필드, 또는 getName()
과 같은 메소드 앞에 붙은 public
은 접근지정자(access specifer) 라고 한다. 다른 클래스에서 접근할 수 있는 정도를 선언하는 것이다. 자세한 내용과 필요성은 나중에 더 알아보도록 하자.
생성자
위 코드에서 public Human() {}
라고 구현된 메소드가 있다. 이 메소드는 뭔가 특별해 보인다. {}
안에 구현되어 있는 것도 없고(배우다 보면 알게 되겠지만 구현해야할 때도 있다), 메소드의 이름도 클래스의 이름과 똑같다. 이러한 조금 특별한 메소드를 생성자라고 부른다. 이는 객체가 생성될 때 자동으로 호출되는 메소드이다. 자세한 내용은 차후에 기회가 될 때 알아보겠다.
public static void main(Strings args[]) {
Human human1; // Human 객체에 대한 레퍼런스 변수 human1 선언
human1 = new Human(); // Human 인스턴스 생성
Human human2 = new Human();
// Human 객체에 대한 레퍼런스 변수 human2를 선언하며 동시에 인스턴스 생성
human1.name = "유민규"; // human1 인스턴스의 name 필드에 이름 값 저장
human1.bloodType = 'O'; // human1 인스턴스의 bloodType 필드에 혈액형 값 저장
human2.name = "박민선"; // human2 인스턴스의 name 필드에 이름 값 저장
human2.sex = "Female"; // human2 인스턴스의 sex 필드에 성별 값 저장
human2.job = "Designer"; // human2 인스턴스의 job 필드에 직업 값 저장
human1.getName(); // human1의 이름 출력
human2.getName(); // human2의 이름 출력
human1.getBloodType(); // human1의 혈액형 출력
human2.getJob(); // human2의 직업 출력
}
레퍼런스 변수 선언
인스턴스를 생성하기 이전에, 그 인스턴스를 가리킬 수 있는 레퍼런스 변수를 생성해야 한다. Human human1;
이 바로 그 코드이다. 하지만 이것으로 그 클래스에 해당하는 인스턴스를 생성이 완료된 것은 아니다. 말 그대로 그 인스턴스를 가리기는 레퍼런스 변수만 생성했을 뿐 인스턴스 그 자체는 생성되지 않은 것이다.
인스턴스 생성
일단 레퍼런스 변수를 생성하였으니 인스턴스를 생성해야겠다. 인스턴스 생성에는 new
연산자를 이용한다. human1 = new Human();
가 그 코드이다. 먼저 선언해놨던 레퍼런스 변수에 new
연산자와 생성자를 이용하여 Human
이라는 타입 크기의 메모리를 할당하고 생성자 코드를 실행한다. 하지만 앞선 Human
클래스의 구현에서는 각각의 멤버를 따로 초기화하지 않았다. 인스턴스가 생성됨과 동시에 각 필드를 초기화하거나 필요한 작업을 위해 두는 것이 생성자인데 public Human() {}
와 같이 따로 구현해 둔 것이 없다. 따라서 말 그대로 필드들이 값을 가짐 없이 생성만 된 상태이다. 추가적으로 Human human2 = new Human();
와 같이 레퍼런스 변수 선언과 인스턴스 생성을 동시에 할 수 있다.
멤버 접근
human1.name = "유민규";
human1.bloodType = 'O';
human2.job = "Designer";
와 같은 코드들은 인스턴스 내의 멤버에 접근하는 방법을 보여주고 있다. 인스턴스 내의 멤버 접근은 인스턴스 레퍼런스.멤버
의 포맷으로 가능하다. 그리고 앞서 봤던 코드들처럼 그 값을 변경 및 저장할 수 있다. 인스턴스 내의 필드 뿐만 아니라 메소드에도 접근 및 호출할 수 있다. 같은 방법으로 human1.getName();
human2.getJob();
의 방식으로 호출할 수 있다.