수업내용/Java

[2022.09.13.화] 객체지향(클래스,객체)

주니어주니 2022. 9. 13. 19:16

 

https://github.com/eungsu/documents/blob/master/01-java/07-oop-02-%EA%B0%9D%EC%B2%B4%EC%99%80%ED%81%B4%EB%9E%98%EC%8A%A4.md

 

GitHub - eungsu/documents

Contribute to eungsu/documents development by creating an account on GitHub.

github.com

 

객체지향 프로그래밍

 

  • 부품에 해당하는 객체를 생성하기 위한 설계도(class) 생성
    -> 부품에 해당하는 객체(instance, object, bean) 생성
    -> 그 객체들을 조립해서 소프트웨어 개발 

  • 현실세계에 있는 것을 모델링을 통해 자바에 구현 
    객체 모델링  -> uml 다이어그램(산출물) -> 클래스 설계
    (어떤 객체를 만들고 어떻게 조립을 할 것인지 분석, 설계를 통해 모델링을 하고, 
      모델링 언어인 uml 다이어그램을 통해 산출물을 만들어 내면,
      그 산출물로 클래스를 설계) 

 

객체지향프로그래밍 언어의 주요 장점

  • 코드의 재사용성 
    - 기존의 코드를 이용해서 쉽게 작성 가능 (상속) 
  • 코드 관리 용이
    -쉽게 코드 변경 가능. 느슨한 결합. (조립, 디자인패턴)
  • 신뢰성 높음
    - 데이터 보호, 중복 제거, 오동작 방지 (캡슐화, 중복제거, 리팩토링) 

 

객체지향프로그래밍의 주요 특징

  • 캡슐화 (은닉화, 오작동 방지) 
    - 다른 객체는 객체의 내부구조를 알 수 없고, 공개된 속성과 기능만을 이용 가능
    - 잘못된 사용으로 인한 객체의 손상 방지
    - 접근제한자를 통해 공개할지 숨길지 결정 가능

  • 상속 (생산성)
    - 하위클래스가 상위클래스의 필드와 메소드를 이용 가능
    - 빠르게 대응 가능

  • 다형성 (확장성)
    - 방법은 같은데 객체가 다르면 결과가 다르게 출력
    - 코드의 변경을 최소화하면서 다양한 기능 이용 가능
    - ex) 어떤 객체가 조립되느냐에 따라 데이터 저장방식이 달라짐  

 

객체

 

  • 객체: 물리적, 추상적으로 존재하며, 다른것과 식별가능한 것
             클래스의 인스턴스(실제로 메모리상에 할당되는 것)다. 
             프로그램의 대상이 되는 것 ( 프로그램의 대상이 되는 범위 = 도메인 ) 

  • 객체는 고유한 속성, 기능을 가짐
    - 속성: 다른 객체와 구분되는 고유한 성질 ≒ 필드 ≒ 변수
    - 기능: 고유한 기능 ≒ 메소드
    (자바에서 대부분 기능은 노출, 속성은 가려져 있음 (메소드-공개, 속성-비공개)
     공개된 기능을 통해서 속성을 조절함) 

  • 객체는 독립적으로 존재하며, 객체의 메소드를 통해 상호작용
  • 객체 간 관계 : 집합관계, 사용관계, 상속관계

  • 현실세계의 대상의 속성, 동작 -> 객체 모델링 -> 클래스 설계 -> 객체 생성

  • 하나의 클래스로 여러 객체를 만들 수 있음
    하나의 클래스를 참조하는 이 객체들은 서로 구분됨! 

 

 

클래스

 

  • 객체를 생성하기 위한 설계도 

 

  • 클래스의 구성요소 : 필드, 메소드, 생성자
    (클래스의 필드, 메소드 -> 객체의 속성, 기능 : 인스턴스화) 

 

  • 필드 (≒속성 ≒변수)
    - 객체의 고유한 속성
    - 변수와 비슷한 형태
    - 객체를 생성하면 객체의 변수는 자동으로 해당 데이터타입의 기본값으로 초기화
      (byte, short, int, long = 0
       float, double = 0.0
       char = '\u0000'
       boolean = false
       나머지 = null)
    - 생성자와 메소드 전체에서 사용 가능
    - 객체가 소멸되지 않는 한 객체와 함께 유지

정보시스템 (일반적으로 우리가 개발하는 프로그램)

- 정보시스템은 개인이나 집단에게 유용한 정보를 제공하는 시스템
- 자바로 개발하는 대부분의 프로그램은 정보시스템이다.
- 정보시스템은 업무처리, 의사결정, 조직원 간의 의사소통 등을 목적으로 구축된다. 
- 정보 시스템은 데이터를 입력받아 처리하여 정보를 산출하는 시스템. 기업환경에서 업무처리나 경영 의사결정에 필요한 데이터를 수집, 저장, 가공, 배분하는 시스템 

정보 (목적을 가지고 가공한 것) 

- 특별한 목적을 수행하기 위해서 가공된 데이터
- 정보는 다양한 타입의 값으로 구성되어 있다. (정수, 문자열, ...) 
- 자바에서는 객체로 정보를 표현한다.
 (객체 안에 문자열, 정수 등을 담는 변수가 있어야되는데, 이 변수를 만들게 하는 선언이 필드.
  필드는 변수의 형태(값을 담는 저장소이기 때문에). 하나의 설계도 안에는 변수의 종류도 다양해 ) 

 

* 데이터를 표현할 때

  • 값 1개
    변수
    int score; 
    String name;

  • 동일한 타입의 값 여러 개
    배열 
    int[] scores = new int[10];
    String[] names = new String[10];

  • 다양한 타입의 값 여러 종류
    객체  <-- 사용자정의 자료형
    (int, String 이런게 아니라 나만의 자료형 Book을 만든 것
    ∵ 우리가 표현하는 정보가 동일한 타입의 값으로 이루어져 있지 않고 다양한 타입의 값으로 되어있기 때문에) 
    ( ∴ 다양한 타입의 값 여러종류를 이용하기 위해 객체를 사용하는 것) 
    public Book {
       int no;
       String title;
       String writer;
       int price;
       double discountRate;
    }

* 동일한 자료형이면 배열로 묶을 수 있지만,
   각각 다른 다양한 자료형인데 서로 연관있는 값들이므로, 한 객체에 모아놓음!  

 

 

  • 메소드, 생성자 -> 다음시간에

 

 

 

객체지향 프로그래밍 개발 단계

 

1. 클래스 설계
2. 클래스로 객체 생성
3. 생성된 객체의 속성과 기능 이용 

 

 

1. 클래스 설계

public class Person {

}

 

 

 

2. 객체의 생성과 참조형 변수

  • new 연산자 사용
    • 객체를 메모리의 힙(Heap)영역에 생성 (=클래스영역, 메소드영역, 객체영역 중 객체영역)
    • 메모리에서 객체가 위치하고 있는 객체의 주소값 반환
    • new연산자가 반환하는 주소값을 저장하기 위한 참조변수 필요
  • 클래스명 참조변수 = new 클래스명();
    (이 설계도로 만든 객체의 주소값을 참조변수에 저장하겠다)

 

  • 클래스의 필드, 메소드 -> 객체의 속성, 기능

 

 


 

실습) 

 

  • Person.java : 클래스(설계도) 생성
package day7;

/**
 * 고객 정보를 표현하는 객체 생성에 사용되는 클래스 (설계도)
 * Person 클래스에 속성(변수)들을 설정해 놓음
 * 
 * 고객 정보는 고객번호, 이름, 이메일, 전화번호, 포인트 등으로 구성
 * 			정수	   문자열 문자열  문자열	 정수
 *
 */
public class Person {

	int no;
	String name; 
	String email;
	String tel; 
	int point; 
	Car car;	// 차량정보를 담는 Car타입이어서 기본값이 null
}

 

  • PersonApp1.java : 객체 생성 
    메인메소드가 꼭 필요 
package day7;

public class PersonApp1 {
	
	public static void main(String[] args) {
		
		/*
		 * 클래스로 객체 생성하기
		 * 	클래스명 참조변수 = new 클래스명();
		 */
		Person p1 = new Person();
		Person p2 = new Person(); 
		Person p3 = new Person();
		
		System.out.println(p1);
		System.out.println(p2);
		System.out.println(p3);
	}

}
day7.Person@6f2b958e	//day7패키지의 Person클래스의 해시코드
day7.Person@5e91993f	//해시코드: 객체의 고유한 일련번호
day7.Person@1c4af82c

* 해시코드: 문자열의 길이에 상관없이 객체마다 크기가 일정한 객체 고유의 일련번호
                   거꾸로 해시코드를 보고 문자열의 원본을 알아낼 수 없음 

 

  • 고객정보를 표현하는  Person객체를 생성하고, 고객정보 저장하기 
package day7;

public class PersonApp2 {
	
	public static void main(String[] args) {
		// 고객정보를 표현(저장)하는 Person 객체를 생성하고, 고객정보를 저장하기
		
		// 김유신 고객의 정보를 저장하는 Person 객체 생성하기
		Person person1 = new Person();
		// 이순신 고객의 정보를 저장하는 Person 객체 생성하기
		Person person2 = new Person(); 
		// 류관순 고객의 정보를 저장하는 Person 객체 생성하기
		Person person3 = new Person();
		
		// 객체와 참조변수 1개씩만 있으면, 변수를 더 만들지 않아도 많은 데이터를 관리할 수 있다.
		// person1 참조변수로 고객의 번호, 이름, 이메일, 전화번호, 포인트를 관리할 수 있게 되었다. 
		person1.no = 1000;	// Person 클래스
		person1.name = "김유신";
		person1.email = "kim-ys@naver.com";
		person1.tel = "010-0000-0000";
		person1.point = 23000;
		
		person2.no = 2000;
		person2.name = "이순신";
		person2.email = "lee-ss@naver.com";
		person2.tel = "010-9999-9999";
		person2.point = 35000;
		
		person3.no = 3000;
		person3.name = "류관순";
		person3.email = "ryu-ks@naver.com";
		person3.tel = "010-3333-3333";
		person3.point = 60000;
		
	}

}

 

  • 이미지로 표현

- Person person1 = new Person(); 
  고객정보를 저장하고 다루기 위해서 Person 객체 생성 

 

- Person.class 설계도 안에는 필드들이 있음

 

- Person 클래스를 이용해서 메모리영역의 객체영역에 Person 객체가 생성됨

 

- 이 객체가 2개 생성, 각 객체마다 주소값이 다름 (0x1111, 0x2222)

 

- 메소드 영역에 참조변수 2개 생성, 이 변수가 0x1111, 0x2222 객체를 각각 참조

 

- 참조변수를 통해서 두 객체를 관리할 수 있음

 

- person1.no = 1000;

  person1이 바라보는 객체 안에 있는 no변수에 1000 대입

 

- Person 객체 2개가 모두 동일한 Person.class 클래스로부터 만들어진 것

 메소드 영역에는 변수 person1,2가 저장, 이 변수들은 각 객체를 참조하는 참조변수

 이 참조변수를 이용해서 Person객체의 속성, 기능을 사용할 수 있다. 

 

 

 

  • Person person = new Person(); 살펴보기
package day7;

public class PersonApp3 {
	
	public static void main(String[] args) {
		
		/*
		 * Person person = new Person(); 살펴보기
		 * 
		 * 	Person 
		 * 	- 참조변수의 타입
		 * 	- Person 클래스로 생성한 Person 객체의 주소값을 담는 변수를 정의
		 * 
		 * 	person 
		 * 	- 참조변수의 이름
		 * 	- 변수의 타입이 Person이기 때문에 Person객체의 주소값을 저장하는 참조변수
		 * 	- person 참조변수가 참조하는 객체의 속성, 기능을 사용할 때 이용
		 * 
		 * 	new 
		 * 	- 객체를 생성시키는 명령어
		 * 	- 메모리의 객체영역 (Heap 메모리 영역)에 객체를 생성
		 * 	- 객체가 생성된 곳의 주소값 (Heap 메모리 영역에서 객체가 위치하고 있는 곳)을 반환
		 * 	- new 키워드가 반환한 객체의 주소값을 참조변수 person에 대입
		 * 
		 * 	Person()
		 * 	- 생성자 메소드
		 * 	- 생성자 메소드는 클래스의 이름과 같은 이름을 가지는 메소드
		 * 	- 생성자 메소드는 객체 생성되자마자 실행되는 메소드 
		 * 	- new 다음에만 적을 수 있다.
		 * 	- new 키워드는 생성자 메소드의 이름과 동일한 이름의 설계도를 메모리에 로딩해서 객체를 생성하고,
     	  	 *    생성자 메소드를 실행해서 객체의 주소값을 참조변수가 저장함.
		 */
		Person person1 = new Person();
		System.out.println("person1 참조변수가 참조하는 객체의 속성값 출력하기");
		
		// 객체를 생성하고 객체의 변수에 데이터를 저장하지 않으면, 해당 변수의 기본값으로 초기화된다. 
		System.out.println("번호: "+ person1.no);		// 0
		System.out.println("이름: "+ person1.name);		// null
		System.out.println("메일: "+ person1.email);		// null
		System.out.println("전화번호: "+ person1.tel);		// null
		System.out.println("포인트: "+ person1.point);		// 0
		
		Person person2 = new Person();
		// person2 참조변수가 참조하는 객체의 속성에 값 대입하기
		person2.no = 20;
		person2.name = "강감찬";
		person2.email = "kang-gc@naver.com";
		person2.tel = "010-1111-1111";
		person2.point = 23000; 
		
		System.out.println("person2 참조변수가 참조하는 객체의 속성값 출력하기");
		System.out.println("번호: "+ person2.no);		// 20
		System.out.println("이름: "+ person2.name);		// "강감찬"
		System.out.println("메일: "+ person2.email);		// "kang-gc@naver.com"
		System.out.println("전화번호: "+ person2.tel);		// "010-1111-1111"
		System.out.println("포인트: "+ person2.point);		// 23000
		
	}

}

 

  • 객체의 변수가 가지는 기본값 이미지 
    - 기본 자료형 타입을 제외한 나머지 (문자열, 모든 참조형 타입) : null 
    - null : 참조하고 있지 X 
    - "홍길동"이라는 문자열이 저장되는 것이 X, 그 문자열이 참조하는 객체의 주소값 저장

 

 

  • Car 객체 추가
package day7;

/**
 * 고객 정보를 표현하는 객체 생성에 사용되는 클래스 (설계도)
 * Person 클래스에 속성(변수)들을 설정해 놓음
 * 
 * 고객 정보는 고객번호, 이름, 이메일, 전화번호, 포인트 등으로 구성
 * 			정수	   문자열 문자열  문자열	 정수
 */
public class Car {
	
	String name;	// 모델명 
	String maker;	// 제조사
	int year;		// 연식
	int price;		// 가격
	
}

 

  • 객체의 조립 이미지 

 

- Person p1 = new Person();

 참조변수 p1이 Person 객체를 참조하고 있음

 이 Person 객체 안에는 no, name, email, tel, point 변수가 있음

 이 중 String 타입의 변수는 String 객체를 참조하고 있음

 

- p1.no = 10;

  참조변수 p1이 참조하는 객체의 no변수에 10을 대입

 

- Car genesis = new Car();

  참조변수 genesis가 Car 객체를 참조하고 있음

  이 Car 객체 안에는 name, maker, year, price 변수가 있음

 

- p2.car = genesis;

  참조변수 p2가 바라보는 객체의 car 변수에 genesis변수가 가지고 있는 Car객체의 주소값 대입 

 

 

 

package day7;

public class PersonApp4 {
	public static void main(String[] args) {
		Person p1 = new Person();
		p1.no = 10;
		p1.name = "홍길동";
		p1.email = "hong@naver.com";
		p1.tel = "010-1111-1111";
		p1.point = 23000;
		
		System.out.println("p1 참조변수가 참조하는 Person객체의 속성값 출력하기");
		System.out.println(p1);
		System.out.println("번호: " + p1.no);
		System.out.println("이름: " + p1.name);
		System.out.println("이메일: " + p1.email);
		System.out.println("전화번호: " + p1.tel);
		System.out.println("포인트: " + p1.point);
		System.out.println("보유차랑: " + p1.car);
		System.out.println();
		
//		System.out.println("보유차랑 모델명: " + p1.car.name);	// 실행오류. 
//		System.out.println("보유차랑 제조사: " + p1.car.maker);	
//		System.out.println("보유차랑 출시년도: " + p1.car.year);
//		System.out.println("보유차랑 가격: " + p1.car.price);
		
		// p1.car에는 null값 저장되어있음 (=저장한 값이 없음)
		// = p1.car가 참조하는 객체는 존재하지 않는다.
		// = p1.car.name은 실행오류 (NullPointException 예외 오류)
		// 주의) p1.car가 참조하는 객체가 존재하지 않더라도, p1.car.name 코드가 자동완성 되기는 함. 
		// 		자동완성은 되지만 p1.car에서 더 불러들일 수가 없기 때문에 오류
		// null 값이 대입되어 있는 참조변수로 객체의 속성, 기능을 사용할 수 없다. (NullPointException 오류)
		
		
		Person p2 = new Person();
		p2.no = 20; 
		p2.name = "강감찬"; 
		p2.email = "kang@naver.com";
		p2.tel = "010-2222-2222"; 
		p2.point = 30000;
		
		Car genesis = new Car();		// Car객체의 주소값을 Car클래스의 genesis참조변수에 대입 
		genesis.name = "GV80";			// 참조변수 genesis가 가리키는 Car객체의 변수에 값 대입 
		genesis.maker = "현대자동차";
		genesis.year = 2022; 
		genesis.price = 50_000_000;
		
		// genesis 객체의 주소값을 대입 = p2가 참조하는 Person객체의 car변수에 Car객체를 조립 
		p2.car = genesis;	// p2가 참조하는 Person 객체의 car 변수에 genesis가 참조하고 있는 Car 객체의 주소값 대입
					// p2.car 변수의 주소값 = genesis 변수의 주소값
					// p2.car 변수와 genesis 변수는 같은 객체를 참조하고 있다. 
					// p2.car.name = genesis.name 
		System.out.println("p2 참조변수가 참조하는 고객의 정보 출력하기");
		System.out.println(p2);
		System.out.println("번호: " + p2.no);
		System.out.println("이름: " + p2.name);
		System.out.println("이메일: " + p2.email);
		System.out.println("전화번호: " +p2.tel);
		System.out.println("포인트: " + p2.point);
		System.out.println("보유차랑: " + p2.car);
		System.out.println("보유차랑 모델명: " + p2.car.name);
		System.out.println("보유차랑 제조회사: " + p2.car.maker);	
		System.out.println("보유차랑 출시년도: " + p2.car.year);
		System.out.println("보유차랑 판매가격: " + p2.car.price);
		System.out.println();
		
		Person p3 = new Person();
		p3.no = 30; 
		p3.name = "김유신";
		p3.email = "kim@naver.com";
		p3.tel = "010-3333-3333";
		p3.point = 35000;
		p3.car = new Car();		// Car객체를 생성하고 그 객체의 주소값(아직 값을 입력안한 기본값 상태)을 p3.car변수에 대입
		System.out.println("p3가 참조하는 고객정보의 보유차량정보 출력하기");
		System.out.println("보유차랑 모델명: " + p3.car.name);
		System.out.println("보유차랑 제조회사: " + p3.car.maker);	
		System.out.println("보유차랑 출시년도: " + p3.car.year);
		System.out.println("보유차랑 판매가격: " + p3.car.price);
		System.out.println();
		
		p3.car.name = "그랜져";	// p3.car변수가 참조하는 Car객체에 내용들 입력
		p3.car.maker = "현대자동차";
		p3.car.year = 2021;
		p3.car.price = 40_000_000;
		System.out.println("p3가 참조하는 고객정보의 보유차량정보 출력하기");
		System.out.println("보유차랑 모델명: " + p3.car.name);
		System.out.println("보유차랑 제조회사: " + p3.car.maker);	
		System.out.println("보유차랑 출시년도: " + p3.car.year);
		System.out.println("보유차랑 판매가격: " + p3.car.price);
		System.out.println();
		
	}
}
p1 참조변수가 참조하는 Person객체의 속성값 출력하기
day7.Person@626b2d4a
번호: 10
이름: 홍길동
이메일: hong@naver.com
전화번호: 010-1111-1111
포인트: 23000
보유차랑: null

p2 참조변수가 참조하는 고객의 정보 출력하기
day7.Person@1c4af82c
번호: 20
이름: 강감찬
이메일: kang@naver.com
전화번호: 010-2222-2222
포인트: 30000
보유차랑: day7.Car@379619aa
보유차랑 모델명: GV80
보유차랑 제조회사: 현대자동차
보유차랑 출시년도: 2022
보유차랑 판매가격: 50000000

p3가 참조하는 고객정보의 보유차량정보 출력하기
보유차랑 모델명: null
보유차랑 제조회사: null
보유차랑 출시년도: 0
보유차랑 판매가격: 0

p3가 참조하는 고객정보의 보유차량정보 출력하기
보유차랑 모델명: 그랜져
보유차랑 제조회사: 현대자동차
보유차랑 출시년도: 2021
보유차랑 판매가격: 40000000

 

 

* NullPointException 오류 

참조변수에 null 값이 대입되어 있을 때, 참조하는 객체가 존재하지 않기 때문에

참조변수로 객체의 속성, 기능을 사용할 수 없다. 

 

  • 객체의 조립2 이미지
    - 각 객체의 주소값을 참조변수에 대입(참조) -> 조립

주소값을 갖는 순간 참조

 

 

  • 가비지 객체

Person p1 = new Person();   // Person객체를 생성하고 그 주소값을 p1에 대입

Person p2 = p1;                     // p1의 값을 p2에 대입 ( 그럼 둘다 Person객체의 주소값을 똑같이 갖게됨 )

p1 = null ;                               // p1에 null을 대입하면 이때 참조가 끊어짐

p2 = null ;                              // 얘도 null을 대입할때 참조가 끊어짐 (p1에 null대입 후에 p1값을 p2에 대입한게X니까)

 

-> Person 객체를 참조하는 참조변수가 하나도 없어짐.

이 객체를 다시 참조할 수 있는 방법이 없음

-> 가비지(Garbage)객체