국비교육(22-23)

13일차(4)/java(5) : class, field, method / static method

서리/Seori 2022. 10. 24. 23:07

13일차(4)/java(5) : class, static

 

- 새 프로젝트 안에 패키지 2개 만들기 (test.main / test.mypac)

 


- heap 영역 안에 만들어지는 것은 객체이고,
 이 객체저장소(field) + 기능(method) 으로 이루어져 있다.

- class 란 객체의 설계도 역할을 하며, 객체가 어떤 필드와 어떤 메소드를 가질지 설계한다!

 

- 지금까지 사용한 메소드 length, replace, startWith ... 등은 
전부 이미 클래스로 설계가 되어있기 때문에 그런 기능을 가지는 것!

- 아래에서는 설계도를 직접 만들어서 원하는 필드, 메소드를 가지는 객체를 만들어볼 예정!
→ 설계도를 어떻게 만드는지 / 만든 설계도로 객체를 어떻게 만드는지 실습

 

- MainClass 파일은 메인메소드를 만들기위해서 만들었던 클래스. java에서 메소드는 단독으로 존재할 수 없다.
- javascript에서는 함수가 단독으로 존재할 수 있었다.
→ 하지만 자바에서는 메소드를 단독으로 만들 수 없다. 반드시 클래스 안에 정의해야 한다!

- 그 클래스를 사용해 객체를 만들었을 때 어떤 메소드와 어떤 필드를 가질지 설계하고,
 설계된 대로 객체를 실체화시키는 연습을 하기
- '설계도'와 '실체'를 별도로 생각하기! ex) 아이폰의 설계도 / 아이폰

 


 

mypac 안에 <Car> class 생성

package test.mypac;
/*
 * class의 역할
 * 
 * 1. 객체의 설계도 역할
 * 2. data type 역할
 * 3. static 필드와 메소드를 포함하는 역할
 */
public class Car {
	//저장소(field)
	public String name;
	
	//달리는 기능(method)
	public void drive() {
		/*
		 * 이 클래스로 객체가 생성된다면 바로 그 객체의 참조값을 가리키는 예약어가 this이다.
		 */
		System.out.println(this.name+" 이(가) 달려요!");
	}
	
	//멈추는 기능(method)
	public void stop() {
		System.out.println("멈춰요!");
	}
}

 

<MainClass01>

package test.main;

import test.mypac.Car;

public class MainClass01 {
	public static void main(String[] args) {
		//test.mypac 패키지에 있는 Car 클래스로 객체를 생성해서 참조값을 얻어냈지만 사용하지 않고 버리기
		new Car();
		//test.mypac 패키지에 있는 Car 클래스로 객체를 생성해서 참조값을 얻어내서 car1이라는 지역변수에 담기
		Car car1=new Car();
		//필드에 값 대입하기
		car1.name="소나타";
		//메소드 호출하기
		car1.drive();
		car1.stop();
		
		Car car2=new Car();
		car2.name="람보르기니";
		car2.drive();
		car2.stop();
	}
}

 

- new(예약어)에서 객체가 만들어진다. (new 총 3번)
→ 1은 버려지고 (참조값을 불러왔지만 어디에도 대입하지 않음)
    2는 car1이라는 객체에 값이 들어감
    3은 car3이라는 객체에 값이 들어감

 

[ class의 역할 ]
1. 객체의 설계도 역할
2. data type 역할
3. static 필드와 메소드를 포함하는 역할

 

- Car이라는 클래스를 만들어 MainClass에서 import시켜 실행시켜보기!

- Car이라는 클래스는 name이라는 필드와 drive, stop 이라는 메소드를 가진다.

 (car이라는 가상의 설계도를 만들어볼 것)

 

[자동 import 하는 방법 2가지]
1) 클래스명을 작성하고 ctrl+space
2) ctrl+shift+o

- import는 패키지가 다르면 꼭 해야하는 것!

 상단에 패키지명.폴더명.클래스명 으로 표기하면 된다.

 

- javascript에서는 function drive(){} 비슷한 느낌

- javascript에서는 함수가 단독으로 존재할 수 있고 drive() 로 호출이 가능했음.
 but java에서는 함수가 단독으로 존재하지 못함. class로 만들어주어야 한다.

 

- Car 이라는 클래스 안에 가상의 달리는 기능 drive를 만들었다고 하자.

 객체를 사용해서 heap 영역의 drive라는 기능을 불러올 수 있다.

 → 사물함 키 값만 가지고 있으면 언제든 drive라는 기능을 사용할 수 있다.

 

 

name: 필드, 저장소
drive/stop: 메소드, 기능

- 클래스란 설계도이기 때문에, 동일한 저장소와 기능을 여러 개 만들 수도 있다. 설계도니까!
 객체를 원하는만큼 만들어낼 수 있다.(이 때, 호출할 때마다 다른 사물함 key를 가진다.)
- 키만 있으면 언제든 저장소 참조와 기능 사용이 가능.

 


 


- new 클래스(); : 클래스의 호출은 new라는 예약어와 함께 사용한다!

 

- class 자체가 데이터 타입의 역할도 한다.
 → Car 클래스로 변수를 새로 만든다면 새로 만든 변수의 데이터타입은 Car type 이다.

 

- car1 변수를 보면 사전에 만든 필드(name), 메소드(drive, stop) 를 갖고있는 것을 볼 수 있다.

 

Car car1=new Car(); : Car() 를 호출하여 리턴값을 car1이라는 변수에 대입해준 상태

 

- 디버깅해보면 name이라는 필드에 null이 들어있다.
 (public string name; 이라고 필드를 선언만 하고 값을 넣어두지 않았기 때문에)
- 지역변수는 선언만 하면 만들어지지도 않지만, 필드는 선언만 해도 null이 들어간다.

 

car1.name="소나타";

 

- 한줄을 추가해 준 후에 다시 디버깅해보면 null이었던 곳에 값이 들어가는 것을 볼 수 있다!

 

 

- 필드에 있는 값을 참조할 때는 this 사용

 

- 같은설계도로 실행했는데, 내용이 다르게 나온다.
- 동일한 설계도라도 필드에 있는 내용이 다르기 때문에 결과가 다르게 나온 것.
 → 필드의 내용이 다르면 메소드의 동작이 다르게 나타날 수 있다.

 

 


 

Q) 객체의 필드와 메소드를 활용해서 프로그래밍을 하는데
동일한 기능을 가진 객체가 여러 개 있을 필요가 있을까??

 

A) 객체에 한명의 회원정보 / 하나의 글정보 / 하나의 상품정보 등을 담을 예정
만약 회원이 여러명이고, 글이 여러개고, 상품이 여러개라면?
→ 객체 하나만 생성해서는 안된다. 객체가 회원의 개수만큼 필요할 것!
→ 동일한  기능을 가진 여러개의 객체가 필요한 이유이다.

 

 

- java의 '객체'를 javascript에서 대응시킨다면 object라고 생각하면 된다.

 car = {name:"xxx", drive:function(){}, stop:function(){} }; 인 것!

 



- this라는 예약어는 heap영역의 객체 안에서 자기자신의 참조값을 가리키는 것이다.
 똑같은 클래스로 객체를 생성했다면 객체마다 똑같은 name이라는 필드가 있다.

- this.name이란 객체 안에서 자신의 참조값을 가리키는 것으로 위 그림에서는 24, 25에 해당한다.

 

- 설계 단계에서는 this가 무엇을 가리킬 것인지 모른다.

 

- 각각의 객체마다 this가 다르다. this는 참조값이다!

 

- 28번 사물함 안에서 this는 28, this.name="소나타"

  29번 사물함 안에서 this는 29, this.name="람보르기니"

 


 

static method ↔ non-static method


- 어떤 파일을 run 하려면 아주 특별한 static main method 가 필요하다. (static: 고정된, 정적인)
 run하면 해당 main method 부터 실행이 시작된다.
- static 메소드와 non-static 메소드는 실행 방법이 다르다.


 

- static 메소드의 기능, non-static 메소드와의 차이 구분

 

test.main 안에 MainClass02 / test.mypac 안에 MyUtil이라는 새 클래스 생성.

 

<MyUtil>

package test.mypac;

public class MyUtil {
	//필드
	public static String version;
	
	//메소드
	public static void send() {
		System.out.println("전송합니다.");
	}
}

 

<MainClass02>

package test.main;

import test.mypac.MyUtil;

public class MainClass02 {
	public static void main(String[] args) {
		//static 메소드는 클래스명에 . 찍어서 바로 호출할 수 있다.
		MyUtil.send();
		//static 필드는 클래스명에 . 찍어서 바로 호출할 수 있다.
		MyUtil.version="1.0";
	}
}

- static field 와 static method를 가진 클래스 MyUtil의 사용법

 

- MyUtil은 static field 와 static method를 가진다.(아이콘 위에 S가 붙어있다)

 각각 string 타입, void 로 정의되어 있다.

 

- Car은 car1이라는 변수에 클래스를 대입해두고 그 참조값(key)을 사용해서 호출한다.

 

- 하지만 MyUtil은 클래스명에 . 을 찍어서 바로 쓴다.

 바로 static때문에!! static 예약어가 있으면 new를 쓸 필요가 없다.

 

- 필드와 메소드를 선언할 때 static이 붙었느냐 안붙었느냐는 큰 차이가 있다!!

 

 


 

* static, stack, heap의 3가지 영역이 존재한다고 생각해야 한다.

static   stack   heap
static 자원이 만들어지는 영역 지역변수가 만들어지는 영역 객체가 만들어지는 영역
class 안에 
static 필드, static 메소드가 만들어진 채로 클래스가 올라간다.

클래스명으로 구분되는 영역
  객체 안에 필드, 메소드가 만들어지고

참조값(사물함 번호)로 구분되는 영역

- static 영역은 객체와 상관이 없다.

 여러개의 클래스가 올라가게 된다. (각각의 클래스는 클래스명으로 구분된다.)

 

- heap은 실체(객체)를 만들어낸 다음, 그 실체를 참조하는 것이다.

 new로 새롭게 호출할 때마다 객체를 여러 번 만들어낸다.(똑같이 호출하나 다른 참조값을 가지는 객체를 만듦!)

 

ex) static에서는 MyUtil.XX 로 찾는다. (바로 클래스명으로!)

   heap영역은 참조값 대입해서 car1.XX, car2.XX, ... (car1에는 참조값이 대입된다)

 

- 필드를 만들거나 메소드를 만들 때 static을 붙여주면 클래스와함께 static영역에 올라간다.

 

 

- heap영역에서 불러오는 모양! (24, 25라는 참조값을 사용해서 접근한다.)

- 지역변수는 stack영역에서 만들어짐. 참조값을 지역변수에 담아두고 필요할때 쓰는 것.

 

- static이냐, non-static이냐에 따라 사용법이 다르다. 잘 구분하기!

 

 

- static은 번호로 구분되는 사물함이 아니다. 당연히 클래스명으로 접근한다. (A, MyUtil을 사용해서 접근)

 (static은 오직 하나, only one, single이라는 의미도 있다.)

- static이라는 메소드를 만들면 그 메소드는 오직 하나밖에 만들어지지않는다.

 (왜냐하면 클래스당 하나씩만 올라가니까!)

 

- MyUtil안에는 version이란 이름의 필드와 send라는 이름의 메소드가 있다.

- static 영역에 만들어진 필드, 메소드를 사용할때에는 class명을 사용해서 접근한다.