JAVA 웹 개발/1. JAVA
05. 객체
코딩 펭귄
2022. 5. 10. 15:28
📅 2021.08.18 ~ 2021.08.20
객체(Instance)
- 현실에 존재하는 독립적이면서 하나로 취급되는 사물이나 개념으로, 컴퓨터, 사람, 핸드폰, 공기, 사랑 등 구체적인 것부터 추상적인 것까지 모든 것을 객체라고 한다.
- 자바에서의 객체(Object) : 클래스에 정의된 내용으로 new 연산자를 통해 Heap 메모리 영역에 생성된 것을 말한다.
- 객체 지향 언어 : 객체의 개념을 컴퓨터로 옮겨 놓은 것을 객체 지향 프로그래밍이라고 하는데, 이 객체 지향 프로그래밍을 할 때 필요한 언어를 객체 지향 언어라고 한다.
- 객체 지향의 3대(4대) 특징(★)
- 캡슐화 : 데이터를 외부에서 볼 수 없도록 은닉하는 것을 말한다.
캡슐화의 원칙
- 클래스의 멤버 변수에 대한 접근 권한은 private을 원칙으로 한다.
- 클래스 멤버 변수에 대한 연산 처리를 목적으로 하는 함수들을 클래스 내부에 작성한다.
- 멤버 함수는 클래스 밖에서 접근할 수 있도록 public으로 설정한다.
※ 멤버 변수 : 클래스 내부, 메소드 외부에 선언되어 있는 변수
- 상속: 클래스 간에도 자식과 부모 관계를 맺을 수 있는데, 이때 부모 클래스가 자식 클래스에 자기가 가진 것을 넘겨주는 것을 말한다.
- 다형성: 한 클래스가 여러 가지 형태로 객체를 만들 수 있는 것을 말한다.
- 추상화: 유연성을 확보하기 위하여 구체적인 것은 제거하고 공통점만 남기는 것을 말한다.
추상화 결과물의 자료형과 변수명을 설정하여 정리된 변수명과 자료형을 클래스 다이어그램으로 도식화할 수 있다. 클래스 다이어그램의 '-'는 데이터 접근제한자로 목록화하기 위해 사용된 단순 기호가 아니라, 클래스 다이어그램에 사용되는 기호이다.
※ 추상화는 객채 지향 4대 특징을 묻는 경우에만 추가가 가능하며, 3대 특징에는 들어가지 않는다.
- 캡슐화 : 데이터를 외부에서 볼 수 없도록 은닉하는 것을 말한다.
- 객체의 할당: new 연산자를 이용해 heap 메모리 공간에 서로 다른 데이터가 연속으로 나열/할당 된 객체 공간을 만드는 것을 의미한다.
Student는 클래스로 참조 자료형이며, 따라서 주소 값을 가지고 있다.Student s = new Student();
클래스
- 클래스의 등장 배경
- 변수: 1개의 데이터를 저장하는 공간 → 여러 개의 데이터를 저장하여야 할 경우 변수를 사용하면 불편하다.
- 배열: 여러 개의 데이터를 저장하는 공간 → 같은 자료형끼리만 저장 가능하기 때문에 여러 가지 자료형을 저장할 경우 배열을 여러 개 만들어 주어야 한다.
- 구조체: 여러 개의 데이터를 자료형에 구애받지 않고 저장이 가능하다. → 해당 중요 데이터에 아무나 접근, 수정이 가능하기 때문에 중요한 데이터인 경우 치명적인 문제가 발생할 수 있다. 하지만, 데이터를 접근, 수정이 불가능하게 하는 경우에는 필요한 경우에 수정이 불가능해진다.
- 인스턴스화: 추상화되어 있는 클래스를 이용하여 객체를 만드는 것을 의미한다.
클래스는 붕어빵 틀이라면 객체는 붕어빵이라고 할 수 있다. 클래스(붕어빵 틀)로 객체의 속성(붕어빵 내용물)을 변경해가며 찍어낼 수 있다. - 클래스 선언
[접근제한자][예약어] class 클래스명 {
[접근제한자][예약어] 자료형 변수명; → 속성값을 설정하는 부분
[접근제한자] 생성자명() {}
[접근제한자] 반환형 메소드명(매개변수) { // 기능 정의 } → 기능을 정의하는 부분
}- 접근제한자: 나에게 접근할 수 있는 것들을 제한하는 것을 의미한다. 총 4가지가 존재하지만, 클래스에서는 두 가지만 사용이 가능하다.
- public(+): 같은 패키지 안에서든 다른 패키지 안에서든 어디에서나 접근이 가능하다. 다음과 같은 형태로 사용된다.
public class 클래스명 {} - default(~): 같은 패키지 안에서는 접근이 가능하지만, 다른 패키지에서는 접근이 불가능하다. 다음과 같은 형태로 사용된다. default는 접근제한자를 붙이는 경우 오류가 발생한다.
class 클래스명 {}
기본적으로 모든 클래스는 public이다.
- public(+): 같은 패키지 안에서든 다른 패키지 안에서든 어디에서나 접근이 가능하다. 다음과 같은 형태로 사용된다.
- 접근제한자: 나에게 접근할 수 있는 것들을 제한하는 것을 의미한다. 총 4가지가 존재하지만, 클래스에서는 두 가지만 사용이 가능하다.
클래스 다이어그램

- 클래스 다이어그램은
데이터 접근제한자 변수명 : 자료형
형태로 작성한다. - 메소드의 경우 자료형이 없으며 소괄호와 매개변수, 반환값을 추가하여 작성한다.
- static인 경우 밑줄로 표시한다.
- final(상수)인 경우 별도의 표시 사항은 없으며, 대문자로 표기한다.
package / import
- package : 서로 관련된 클래스 또는 인터페이스의 묶음으로 소스 파일 첫 번째 문장에 한 번 선언한다. 패키지는 서브 패키지를 가질 수 있으며, '.'으로 구분한다.
- import : 클래스 사용 시 패키지명을 생략하기 위하여 사용한다. 하지만 이름이 같은 클래스가 속한 두 패키지 중 하나의 패키지를 이미 import한 경우, 다른 클래스는 패키지명을 붙여 구분해주어야 한다.
java.lang 패키지 내의 클래스는 import 없이 사용이 가능하다. (ex. System, Math, String 등)
지정된 패키지에 포함된 클래스는 한 번에 import가 가능하지만, (ex. import java.util.*) 서브 패키지에 속한 모든 클래스를 한 번에 import할 수는 없다. (ex. java.util.*로 import한 경우 java.util.zip 패키지 내부의 클래스는 따로 import 해주어야 한다.)
필드 (= 멤버 변수, 멤버 필드, 전역 변수)
- 속성 값 정의 부분(클래스 영역)에 해당하는 것을 필드라고 하며, 표현식은 다음과 같다.
[접근제한자] [예약어] 자료형 변수명 [= 초기값]
[]는 생략 가능 - 전역 변수는 해당 클래스의 전체 영역에 영향을 미친다.
- 클래스 영역이 아닌 메소드 영역에 작성되는 변수는 지역 변수라고 하며, 해당 메소드 내서만 영향을 미친다.
메소드 호출 시 외부에서 데이터를 받아오는 변수는 매개변수라고 하며, 지역 변수의 일종이다.
지역 변수는 쓰레기 값이 들어갈 수 있으므로 항상 초기화한 후 사용하여야 하는데, 매개변수는 항상 값을 가지고 있기 때문에 별도의 초기화를 하지 않아도 된다. - 접근제한자: 총 4개가 존재하며, 필드에는 네 가지 모두 사용 가능하다.
이름 같은 클래스 내부 같은 패키지 내 후손 클래스 내 전체 + public O O O O # protected O O O ~ default O O - private O
- 필드 예약어
- static : 같은 타입의 여러 객체가 공유할 목적의 필드에 사용하며, 프로그램 시작 시 정적 메모리 영역(static 영역)에 자동으로 할당되는 멤버에 적용된다.
객체를 따로 만들지 않아도 프로그램 시작 시 생성되기 때문에 객체를 새로 만든다고 해서 변수가 초기값으로 초기화되지 않는다.
static 변수는 클래스 변수라고도 하며, static이 아닌 변수는 인스턴스 변수라고 한다. 인스턴스 변수는 객체가 새로 생성될 때마다 초기 값으로 초기화된다.
공유하는 변수이기 때문에 보통의 경우 static 변수는 public으로 사용한다.
static 변수는 static 접근 방식을 사용하여 접근하는 것을 권장한다. static 접근 방식을 사용하지 않고 객체를 생성하여 접근하여도 에러가 발생하지는 않으나, "The static field 변수명 should be accessed in a static way"라는 경고가 발생한다.
static 접근 방식 : 객체를 생성할 필요 없이 클래스명.필드명/클래스명.메소드명으로 접근하는 방식을 말한다. - final : 하나의 값만 계속 저장해야 하는 변수(상수)에 사용한다. 변수 뿐 아니라 메소드에도 사용 가능하다.
- static : 같은 타입의 여러 객체가 공유할 목적의 필드에 사용하며, 프로그램 시작 시 정적 메모리 영역(static 영역)에 자동으로 할당되는 멤버에 적용된다.
- 초기화 블럭: 초기화를 할 때 사용되며, 생성자에서 반복되는 초기화가 있는 경우에 편의를 위해 사용된다.
- 인스턴스 블럭 ({ }): 인스턴스 변수를 초기화시키는 블럭으로 객체 생성 시마다 초기화된다.
- 클래스(static) 블럭 (static{ }): static 필드를 초기화시키는 블럭으로 프로그램 시작 시 한 번만 초기화된다.
- 초기화 순서
- 클래스 변수: JVM 기본값으로 초기화 → 명시적 초기값으로 초기화 → 클래스 초기화 블록 초기값으로 초기화
- 인스턴스 변수: VM 기본값으로 초기화 → 명시적 초기값으로 초기화 → 인스턴스 초기화 블록 초기값으로 초기화 → 생성자를 통한 초기값으로 초기화
생성자
- 객체가 new 연산자를 통해 Heap 메모리 영역에 할당될 때 객체 안에서 만들어지는 필드를 초기화하는 역할을 한다. 일종의 메소드로, 전달된 초기 값을 받아 객체의 필드에 기록한다.
- 생성자 표현식 :
[접근제한자] 클래스명(){}
[접근제한자] 클래스명(매개변수){(this.)필드명 = 매개변수;} - 생성자 규칙
- 메소드의 선언과 유사하나 반환값이 없다.
- 생성자명은 클래스명과 같아야 한다. (대소문자 또한 같아야 한다.)
- 생성자 종류
- 기본 생성자: 매개변수에 아무것도 없는 생성자로 작성하지 않아도 JVM이 클래스 사용 시 자동으로 삽입해 준다.
- 매개변수 생성자: 사용하는 경우 별도의 작성이 필요하며, 객체 생성 시 전달받은 값으로 객체를 초기화하는 경우 사용된다.
매개변수 생성자를 작성하는 경우에는 JVM이 기본 생성자를 자동으로 생성하지 않기 때문에 기본 생성자를 별도로 작성해주어야 한다. 기본 생성자가 존재하지 않으면 객체 생성 시 무조건 매개 변수에 값을 입력하여야 생성이 가능하다.
상속에서 사용 시 반드시 기본 생성자를 작성하여야 한다.
오버로딩을 이용하여 작성하여야 한다.
- 생성자는 객체를 만듦과 동시에 필드를 초기화하는 것이기 때문에 메소드에서 필드에 값을 넣어주는 것과는 다르다. 메소드에서 필드에 값을 넣는 경우에는 객체 생성 시 필드에 기본 값이 들어가 있고, 그 이후 값을 할당하는 것이지만, 생성자를 이용해 초기화하는 경우에는 필드에 기본 값이 들어가지 않는다.
오버로딩
- 오버로딩: 한 클래스 안에 동일한 이름의 메소드를 여러 개 작성하는 기법이다. 생성자도 메소드의 일부이므로 오버로딩을 사용할 수 있다.
- 오버로딩의 조건
- 메소드의 이름이 동일하여야 한다.
- 매개 변수의 개수가 다르거나, 매개 변수의 타입이 다르거나, 매개 변수의 순서가 달라야 한다.
※ 매개 변수의 이름이 다른 것은 해당되지 않는다.
this
- 생성자를 사용할 경우 매개 변수와 전역 변수의 이름이 같으면 더 가독성을 높일 수 있다. 하지만 단순히 이름만 같게 한 후 대입하면 전역 변수를 인식하지 못하기 때문에 전역변수에 값을 대입할 수 없다.
그 이유는 지역 변수의 영역에서는 지역 변수가 항상 우선 순위가 되기 때문이다. 따라서 필드(전역 변수)와 지역 변수를 구분해 주어야 하는데 이때 사용하는 것이 참조 변수인 this이다.public User(String userId, String userPwd) { userId = userId; // 전역변수인 userId를 인식하지 못하고, 매개변수 userId에 매개변수 userId를 대입하는 것으로 판단한다. userPwd = userPwd; }
- 모든 인스턴스 메소드에 숨겨진 채 존재하는 레퍼런스(참조)로 할당된 객체를 가리킨다. 이것은 객체가 만들어져야 this가 동작한다는 뜻이다.
- this는 객체 생성 시 전달되는 객체의 주소를 자동으로 받는다. 클래스만 작성된 경우에는 this에 주소값이 저장되지 않으며, 객체가 만들어진 이후에 할당된다.
- this.변수명의 형태로 사용하며, this를 붙여서 사용하는 변수는 필드로 인식한다.
public User(String userId, String userPwd) { this.userId = userId; this.userPwd = userPwd; }
- this는 heap 영역에 객체가 만들어진 이후에 주소값을 가지기 때문에 this로 접근하는 것은 객체를 생성한 후 접근하는 것과 같은 의미를 가진다. 따라서 static인 경우 this를 사용하면 경고가 발생한다.
static의 경우 클래스명.필드명 또는 클래스명.메소드명으로 접근하여야 한다.
this()
- this 생성자로 같은 클래스 내의 다른 생성자를 호출할 때 사용하며, 반드시 첫 번째 줄에 선언하여야 한다.
- 생성자끼리 생성자 내에서의 중복을 방지하는 경우, 혹은 기본 생성자를 호출할 때 값을 넣어주기 위해 사용한다.
public User(String userId, String userPwd, String userName) { this(userId, userPwd); this.userName = userName; }
메소드
- 수학의 함수와 비슷하며 호출을 통해 사용된다. 전달값이 없는 상태로 호출하거나, 어떤 값을 전달하여 호출할 수 있다.
- 함수 내에 작성된 연산 수행 후 반환 값/결과 값은 반드시 존재해야 하는 것은 아니다.
- 메소드 예약어
- static
- final : 종단의 의미로 상속 시 오버라이딩이 불가능하다.
- abstract : 미완성된이라는 뜻으로, 상속하여 오버라이딩으로 완성시켜 사용하여야 한다.
- synchronized : 동기화 처리, 공유 자원에 한 개의 스레드만 접근 가능하게 한다.
- static final (final static) : static과 final의 의미를 동시에 가진다
- 메소드 반환형(★★)
메소드는 항상 반환형을 가지며, 반환값이 있는 경우 항상 return을 작성하여야 한다.
- void: 반환값이 없는 것을 의미한다. 반환값이 없을 경우 생성자와의 혼동을 방지하기 위해 반드시 void를 작성해 주어야 한다.
- 기본 자료형: 연산 수행 후 반환 값이 기본 자료형일 경우에 사용된다. 반환형과 return하는 값의 타입이 항상 동일하여야 한다. 기본 자료형 반환 시 해당 자료형의 데이터(값) 자체가 반환된다.
public int test() { int i = 0; return i; }
- 배열: 연산 수행 후 반환 값이 배열인 경우를 말하며, 배열은 참조 자료형이기 때문에 데이터가 아닌 주소 값을 반환한다. 따라서 반환 시 얕은 복사가 일어난다.
public int[] test() { int[] i = {1, 2, 3}; return i; }
- 클래스: 연산 수행 후 반환 값이 클래스인 경우를 말하며, 클래스 또한 참조 자료형이기 때문에 값 반환 시 주소 값을 반환하고, 얕은 복사가 일어난다.
- 메소드 매개변수
메소드 호출 시 전달되는 값을 말한다.
- () : 매개변수가 없는 경우 소괄호 내부에 아무것도 작성하지 않은 형태로 표기한다.
- 기본 자료형 : 기본형 매개변수 사용 시 값을 복사하여 데이터 자체로 전달하며, 따라서 매개변수 값을 변경하여도 본래 변수의 값은 변경되지 않는다.
- 배열, 클래스 : 참조 자료형으로 값을 전달하는 것이 아니라 주소값을 전달하며, 이때 얕은 복사가 발생한다. 따라서 매개변수를 수정하는 경우 본래의 데이터가 수정된다.
- 가변 인자 : 매개 변수의 개수를 유동적으로 설정하는 방법으로 가변 매개변수 외 다른 매개 변수가 존재하는 경우 가변 매개변수를 제일 마지막 부분에 작성한다.
(자료형 ... 변수명)의 형태로 작성하여 사용하며, 제일 대표적인 가변 매개변수를 사용하는 함수로는 printf가 있다.
- 메소드 표현식
- 매개변수가 없고 리턴값이 있을 때
[접근제한자][예약어] 반환형 메소드명(){기능; return;} - 매개변수가 없고 리턴값이 없을 때
[접근제한자][예약어] void 메소드명(){기능;} - 매개변수가 있고 리턴값이 있을 때
[접근제한자][예약어] 반환형 메소드명(자료형 변수명){기능; return;} - 매개변수가 있고 리턴값이 없을 때
[접근제한자][예약어] void 메소드명(자료형 변수명){기능;}
반환값이 존재하지 않는 경우(void) 해당 함수를 호출한 후 다른 변수에 저장할 수 없다. 저장하려고 하는 경우 에러가 발생한다.
매개변수가 있는 함수를 호출할 경우에는 매개변수의 타입, 순서, 개수를 선언한 함수와 똑같이 맞춰 주어야 한다. - 매개변수가 없고 리턴값이 있을 때
setter
- setter 메소드: 필드에 변경할 값을 전달받아서 필드 값을 변경하는 메소드이다. 값을 변경만 하면 되기 때문에 따로 반환값이 존재하지 않는다.
[접근제한자][예약어] void set필드명 (자료형 변수명) { (this.)필드명 = 변수명}
필드에 있는 데이터가 잘못되어 하나씩 따로 변경하고 싶을 경우에 사용한다. 생성자는 값을 통째로 초기화하는 기능을 하기 때문에 값을 하나만 변경할 수 없다. 새로운 생성자를 만들어 해당 생성자로 객체를 만드는 것은 기존 객체를 수정하는 것이 아니라 새로운 객체를 갱성하는 것이기 때문에 주소 값이 달라진다.
getter
- 필드에 기록된 값을 읽은 후에 요청한 쪽으로 읽은 값을 넘기는 역할을 하는 메소드이다. 값을 넘겨야 하기 때문에 return이 꼭 필요하다.
- [접근제한자][예약어] 반환형 get필드명() { return 필드명; }