현실 세계는 사물이나 개념처럼 독립되고 구분되는 각각의 객체로 이루어져 있으며,
발생하는 모든 사건들은 객체 간의 상호작용이다.
이 개념을 컴퓨터로 옮겨 놓아 만들어낸 것이 객체지향 언어이다.
클래스에 정의된 내용대로 new 연산자를 통해 메모리 영역에 생성된 것
→ new 연산자를 통해 메모리 영역에 생성된 배열도 객체이다
객체의 특성(속성, 기능)에 대한 정의를 한 것
ex) 제품의 설계도, 빵 틀
유연성을 확보하기 위해 구체적인 것은 제거한다는 의미
작성하려는 클래스의 속성과 기능 중
프로그램에서 필요한 공통점을 추출하고, 불필요한 부분을 제거하는 과정
![]() | ![]() |
|---|
→ 앞 페이지에서 추상화한 결과물을 객체 지향 프로그래밍 언어를 사용해서
변수명(데이터 이름)과 자료형(데이터 타입) 정리
추상화를 통해 정리된 데이터들과 기능을 하나로 묶어 관리하는 기법
클래스의 가장 중요한 목적인 데이터의 직접 접근 제한을 원칙으로 하여
클래스 외부에서 데이터의 직접적인 접근을 막고,
대신 간접적으로 데이터에 접근할 수 메소드를 클래스 내부에 작성하는 방법
이로 인해 부가적으로 정보 은닉 효과가 발생함
→ 직접 접근을 못하기 때문에 클래스 내부에
간접 접근 방법을 제공하는 기능(메서드) 작성 ( getter / setter )
클래스의 멤버 변수에 대한 접근 권한은 private을 원칙으로 한다.
클래스의 멤버 변수에 대한 연산처리를 목적으로 하는 멤버 메소드는 클래스 내부에 작성한다.
멤버 메소드는 클래스 밖에서 접근할 수 있도록 public으로 설정한다. ( getter / setter )
| 구분 | 같은 패키지 내 | 전체 |
|---|---|---|
| (+) public | ⭕ | ⭕ |
| (~) (default) | ⭕ |
필드 == 필드변수 == 멤버변수
값을 저장하기 위한 변수 선언
ex) 국민이라면 공통적으로 가지고 있는 속성만 작성(추상화)
↳ 이름, 성별, 주민번호, 주소, 전화번호, 나이
[접근제한자] [예약어] class 클래스명 {
[접근제한자] [예약어] 자료형 변수명 [= 초기값];
}
public class Academy {
public int temp1;
protected int temp2;
int temp3; // 접근제한자 생략 시 (default)
private int temp4; // 캡슐화 원칙으로 private 사용
}
| 구분 | 해당 클래스 내부 | 같은 패키지 내 | 후손 클래스 내 | 전체 |
|---|---|---|---|---|
| (+) public | ⭕ | ⭕ | ⭕ | ⭕ |
| (#) protected | ⭕ | ⭕ | ⭕ | |
| (~) (default) | ⭕ | ⭕ | ||
| (-) private | ⭕ |
public class Academy {
private static int temp1;
}
* static 영역에 생성된 변수는 어디서든지 공유 가능 !!
public class Academy {
private final int TEMP1 = 100; // final 키워드가 붙은 필드명은
// 모두 대문자로 표기
private int temp4;
}
인스턴스 블럭 ( { } ) : 인스턴스 변수를 초기화 시키는 블럭으로
객체 생성시 마다 초기화
static(클래스) 블럭 ( static{ } ) : static 필드를 초기화 시키는 블럭으로
프로그램 시작 시 한 번만 초기화
[접근제한자] [예약어] class 클래스명 {
[접근제한자] static 자료형 필드1 = 10;
[접근제한자] 자료형 필드2 = 20 // 명시적 초기화;
static{ 필드1 = 30; }
{ 필드2 = 40; }
}
"The Matrix" (1999) - 'Construct' Scenes
객체가 new 연산자를 통해 Heap 메모리 영역에 할당될 때
객체 안에서 만들어지는 필드 초기화 + 생성 시 필요한 기능 수행
생성자는 일종의 메소드로 전달된 초기값을 받아서 객체의 필드에 기록
생성자의 선언은 메소드 선언과 유사하나 반환 값이 없으며
생성자명을 클래스명과 똑같이 지정해주어야 함
[접근제한자] [예약어] class 클래스명 {
[접근제한자] 클래스명() { }
[접근제한자] 클래스명(매개변수) { (this.)필드명 = 매개변수; }
}
public class Academy {
private int studentNo; // 필드
private String name;
public Academy() {} // 기본 생성자
public Academy(int studentNo, String name) { //매개변수 있는 생성자
this.studentNo = studentNo;
this.name = name;
}
}
작성하지 않은 경우, 클래스 사용 시 컴파일러가 자동으로 기본 생성자 생성
// [접근제한자] 클래스명() {}
public Student() {
// 객체가 생성될 때 수행할 코드
System.out.println("기본생성자에 의해서 Student 객체 생성");
}
기본생성자 단축키 : ctrl + shift + enter
매개변수 생성자 단축키 : alt + shift + s → Generate Constructor using Fields... -> generate
한 클래스 내에 동일한 이름의 메서드를 여러 개 작성하는 기법
오버로딩 조건
* 메소드의 리턴타입은 오버로딩 조건과 관계 없음
모든 인스턴스 메소드에 숨겨진 채 존재하는 래퍼런스로, 할당된 객체를 가리킴
함수 실행 시 전달되는 객체의 주소를 자동으로 받음
[this 사용 예시]
public class Academy{
private String name;
public Academy() { }
public Academy(String name) { this.name = name; }
}
위와 같이 매개변수를 가지는 생성자에서 매개변수 명이 필드명과 같은 경우
매개변수의 변수명이 우선이므로 this 객체를 이용하여 대입되는 변수가 필드라는 것을 구분해줌
생성자, 같은 클래스의 다른 생성자를 호출할 때 사용, 반드시 첫 번째 줄에 선언해야 함
[this() 사용 예시]
public class Academy{
private int age;
private String name;
public Academy() { this(20, “김철수”); }
public Academy(int age, String name) {
this.age = age; this.name = name;
}
}
수학의 함수와 비슷하며 호출을 통해 사용, 전달 값이 없는 상태로 호출을 하거나
어떤 값을 전달하여 호출을 하며, 함수 내에 작성된 연산 수행
수행 후 반환 값 / 결과 값은 있거나 없을 수 있음
[접근제한자] [예약어] 반환형 메소드명() {
// 기능 정의
}
public int information() {
return studentNo;
}
[접근제한자] [예약어] void 메소드명() {
// 기능 정의
}
public void information() {
System.out.println(studentNo);
}
[접근제한자] [예약어] 반환형 메소드명(자료형 변수명) {
// 기능 정의
}
public String information(String studentName) {
return studentNo + " " + studentName;
}
[접근제한자] [예약어] void 메소드명(자료형 변수명) {
// 기능 정의
}
public void information(String studentName) {
System.out.println(studentNo + " " + studentName);
}
[접근제한자] [예약어] void set필드명(자료형 변수명) {
(this.)필드명 = 자료형 변수명;
}
public void setStudentNo(int studentNo) {
this.studentNo = studentNo;
}
[접근제한자] [예약어] 반환형 get필드명() {
return 필드명;
}
public int getStudentNo() {
return studentNo;
}
getter setter 단축키 : alt + shift + s 또는 상단메뉴 Source
→ Generate Getters and Setters... → selectAll → generate
| 구분 | 클래스 | 패키지 | 자손 클래스 | 전체 |
|---|---|---|---|---|
| (+) public | ⭕ | ⭕ | ⭕ | ⭕ |
| (#) protected | ⭕ | ⭕ | ⭕ | |
| (~) (default) | ⭕ | ⭕ | ||
| (-) private | ⭕ |
| 구분 | 전체 |
|---|---|
| static | static 영역에 할당하여 객체 생성 없이 사용 |
| final | 종단의 의미, 상속 시 오버라이딩 불가능 |
| abstract | 미완성된, 상속하여 오버라이딩으로 완성시켜 사용해야 함 |
| synchronized | 동기화 처리, 공유 자원에 한 개의 스레드만 접근 가능함 |
| static final(final static) | static과 final의 의미를 둘 다 가짐 |
| 구분 | 전체 |
|---|---|
| void | 반환형이 없음을 의미, 반환 값이 없을 경우 반드시 작성 |
| 기본 자료형 | 연산 수행 후 반환 값이 기본 자료형일 경우 사용 |
| 배열 | 연산 수행 후 반환 값이 배열인 경우 배열의 주소값이 반환 |
| 클래스 | 연산 수행 후 반환 값이 해당 클래스 타입의 객체일 경우 해당 객체의 주소값이 반환 (클래스 == 타입) |
| 구분 | 전체 |
|---|---|
| ( ) | 매개변수가 없는 것을 의미 |
| 기본 자료형 | 기본형 매개변수 사용 시 값을 복사하여 전달 매개변수 값을 변경하여도 본래 값은 변경되지 않음 |
| 배열 / 클래스 | 배열, 클래스 등 참조형을 매개변수로 전달 시에는 데이터의 주소 값을 전달하기 때문에 매개변수를 수정하면 본래의 데이터가 수정됨(얕은 복사) |
| 가변인자 | 매개변수의 개수를 유동적으로 설정하는 방법으로 가변 매개변수 외 다른 매개변수가 있으면 가변 매개변수를 마지막에 설정 방법 : (자료형 ... 변수명) |
해당 메소드를 종료하고 자신을 호출한 메소드로 돌아가는 예약어
반환 값이 있다면 반환 값을 가지고 자신을 호출한 메소드로 돌아감

* STACK의 자료구조 : LIFO(Last-Input-First-Out)
- model - 프로그램 로직과 관련되어 있는 데이터를 저장하는 용도, 전부 model
- VO (Value Object) : 값 저장용 객체를 만들기 위한 클래스를 모아두는 패키지
package oop.abstraction.model.vo;
public class People { // 클래스 선언부 (국민 클래스)
// [접근제한자] [예약어] class 클래스명
/*
접근제한자 public : 같은 프로젝트 내에서 어떤 클래스에서든
import 할 수 있음을 나타냄 (== 어떤 패키지에서든)
*/
// 속성
private String name;
private char gender;
private String pNo; // "123456-1234567"
private String address;
private String phone; // "010-1234-1234"
private int age;
private int amount;
//public double bitcoin; // 공통점이 아니므로 제거
// 기능(생성자 + 메서드)
public void tax() {
System.out.println("세금을 냅니다...");
}
public void vote() {
System.out.println("투표를 합니다...꼭 하세요!");
}
// 캡슐화에서 사용할 간접 접근 기능 (getter/setter)
// [접근제한자] 반환형 메서드명() {}
// name 변수의 값을 호출한 쪽으로 돌려 보내주는 간접 접근 기능 중 getter
// void : 반환할 값이 없다(반환형(자료형)이 없다)
public String getName() {
return name;
}
// name 변수에 값을 세팅하는 간접 접근 기능 중 setter
public void setName(String name) {
// 매개변수 String name
// -> String 타입의 데이터를 전달받아 저장하고 있는 변수
// ** this : 현재 객체
this.name = name;
}
// alt + shift + s 또는 상단메뉴 Source
// -> Generate Getters and Setters... 클릭
// -> selectAll -> generate 클릭
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public String getpNo() {
return pNo;
}
public void setpNo(String pNo) {
this.pNo = pNo;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
throw new IllegalArgumentException("음수는 안 된다..");
}
}
}
- Service : 특정 기능(비즈니스 로직)을 제공하는 클래스
package oop.abstraction.model.service;
import oop.abstraction.model.vo.People;
public class AbstractionService {
// public AbstractionService() {} // 기본생성자
public void ex1() {
// People 클래스를 이용해서 국민 객체 만들기
People p1 = new People();
// People p1 : People 객체의 주소를 저장하여 참조하는 변수 p1
// new People() : 새로운 People 객체를 Heap 영역에 생성
// * 클래스 이름이 자료형처럼 사용된다
// == 그래서 클래스를 "사용자 정의 자료형" 이라고도 부른다!!! *
/*
p1.name = "홍길동"; // The field People.name is not visible
p1.gender = '남';
p1.pNo = "123456-1234567";
p1.address = "서울시 중구 남대문로 120 그레이츠청계 3층 E강의장";
p1.phone = "010-1234-1234";
p1.age = 20;
p1.tax();
p1.vote();
System.out.println("p1의 name : " + p1.name);
System.out.println("p1의 gender : " + p1.gender);
System.out.println("p1의 pNo : " + p1.pNo);
System.out.println("p1의 address : " + p1.address);
System.out.println("p1의 phone : " + p1.phone);
System.out.println("p1의 age : " + p1.age);
*/
p1.setName("홍길동");
p1.setGender('남');
p1.setpNo("123456-1234567");
p1.setAddress("서울시 중구 어쩌구");
p1.setPhone("010-1234-1234");
p1.setAge(20);
System.out.println(p1.getName());
System.out.println(p1.getGender());
System.out.println(p1.getpNo());
System.out.println(p1.getAddress());
System.out.println(p1.getPhone());
System.out.println(p1.getAge());
// 본인 객체
// People 클래스 이용하여 mihyun
People mihyun = new People();
//mihyun.age = -100;
mihyun.setName("웃음인");
mihyun.setGender('여');
mihyun.setpNo("123456-1234567");
mihyun.setPhone("010-1234-1234");
mihyun.setAddress("서울시 중구 어쩌구");
mihyun.setAge(100);
System.out.println(mihyun.getName());
System.out.println(mihyun.getGender());
System.out.println(mihyun.getpNo());
System.out.println(mihyun.getAddress());
System.out.println(mihyun.getPhone());
System.out.println(mihyun.getAge());
// 다른 라이브러리 + 기술
// getter/setter
}
}
package edu.kh.oop.abstraction.run;
import edu.kh.oop.abstraction.model.service.AbstractionService;
public class AbstractionRun { // 실행용 클래스
public static void main(String[] args) {
// 서비스 클래스 객체 생성
AbstractionService as = new AbstractionService();
// AbstractionService 클래스에 기본생성자를 생성한 적 없지만 기본생성자 호출, 객체도 잘 만들어서 사용 중...
// 어떻게 가능한가?
// -> 컴파일러가 코드를 번역할 때 클래스 내부에 생성자가 하나도 없다면
// 자동으로 기본생성자를 추가해줌(우리 눈엔 안 보임)
// 그 객체에서 ex1() 호출
as.ex1();
}
}
[vo]
public class User {
// 속성 ( 필드 )
// 아이디, 비밀번호, 이름, 나이, 성별 (추상화 진행)
// 데이터 직접접근 불가 원칙 -> 필드는 기본적으로 모두 private (캡슐화 진행)
private String userId;
private String userPw;
private String userName;
private int userAge;
private char userGender;
// 기능 (생성자 + 메서드)
/*
- new 연산자를 통해서 객체를 생성할 때
생성된 객체의 필드값 초기화 + 지정된 기능을 수행하는 역할
*/
// 기본생성자(-> 매개변수 없는 생성자)
public User() {
// 기능
System.out.println("기본생성자로 User 객체 생성");
// 필드 초기화
userId = "user01";
userPw = "pass01";
userName = "홍길동";
userAge = 20;
userGender = '남';
}
// 매개변수 생성자
// ** 사용되는 기술, 변수 : 매개변수, Overloading(오버로딩), this
// ** 매개변수 : 생성자나 메서드 호출 시 () 안에 작성되어
// 전달되어지는 값을 저장하고 있는 변수
// -> 전달받은 값을 저장하고있는 매개체 역할의 변수
public User(String userId, String userPw) {
System.out.println("매개변수 생성자를 이용하여 User 객체 생성");
System.out.println(userId + " / " + userPw);
// 필드 초기화
this.userId = userId;
this.userPw = userPw;
// 필드 = 매개변수
// this 참조변수
// - 객체가 자기 자신을 참조할 수 있도록 하는 변수
// 왜 사용?
// -> 필드명과 매개변수명이 같은 경우
// 이를 구분하기 위해서 사용한다.
}
// 필드를 전부 초기화하는 목적의 매개변수 생성자
public User( String userId, String userPw, String userName,
int userAge, char userGender ) {
// this() 생성자
// 같은 클래스의 다른 생성자를 호출할 때 사용
// 생성자 내에서 반드시 첫번째 줄에 작성해야한다!
// 왜 사용하는가?
// 중복 코드 제거, 코드 길이 감소, 재사용성 증가..
// 가독성이 좀 떨어지는 경우가 있다(단점)
this(userId, userPw);
//this.userId = userId;
//this.userPw = userPw;
this.userName = userName;
this.userAge = userAge;
this.userGender = userGender;
}
// 자바는 기본적으로 필드명, 생성자명, 메서드명, 변수명 의
// 중복을 허용하지 않음.
// private String userId; // Duplicate field User.userId
// public User() {} // Duplicate method User() in type User
// *** 오버로딩(Overloading) ***
// - 클래스 내에 동일한 이름의 메서드(생성자도 포함)를
// 여러 개 작성하는 기법
// [오버로딩 조건]
// 1) 메서드의 이름이 동일
// 2) 매개변수의 개수, 타입, 순서 중 1개라도 달라야 함.
// public User() {} // 기본생성자가 이미 작성되어있어서 X
public User(String userId) {} // 매개변수의 개수가 같은 생성자 없음
// -> 오버로딩 성립
public User(int userAge) {} // 매개변수의 개수는 같지만 타입이 다름
// -> 오버로딩 성립
public User(String userId, int userAge) {}
// 매개변수의 개수와 동일한것이 있으나, 하나의 타입이 다름
// -> 오버로딩 성립
public User(int userAge, String userId) {}
// 매개변수의 개수, 타입은 같지만 순서가 다름
//public User(int userAge, String userName) {} // 에러
// 매개변수의 개수, 타입, 순서가 모두 같아서 불가
// -> 변수명은 신경쓰지 않는다.
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserPw() {
return userPw;
}
public void setUserPw(String userPw) {
this.userPw = userPw;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
public char getUserGender() {
return userGender;
}
public void setUserGender(char userGender) {
this.userGender = userGender;
}
}
[service]
public void ex3() {
// 생성자 확인 테스트
// User 기본 생성자를 이용해서 객체 생성 u1
User u1 = new User();
System.out.println(u1.getUserId());
System.out.println(u1.getUserPw());
System.out.println(u1.getUserName());
System.out.println(u1.getUserAge());
System.out.println(u1.getUserGender());
User u2 = new User();
System.out.println(u2.getUserId());
System.out.println(u2.getUserPw());
System.out.println(u2.getUserName());
System.out.println(u2.getUserAge());
System.out.println(u2.getUserGender());
// 문제점 : u1이 참조하고있는 User 객체와
// u2가 참조하고있는 User 객체의 필드값이 모두 동일함
// 왜? 같은 기본생성자로 User 객체를 생성했기 때문에
System.out.println("--------------------------------");
// 해결방법 1 : setter 를 이용해서 새로운 값 대입
u2.setUserId("asd1234");
u2.setUserPw("1w2e3r");
u2.setUserName("김영희");
u2.setUserAge(25);
u2.setUserGender('여');
System.out.println(u2.getUserId());
System.out.println(u2.getUserPw());
System.out.println(u2.getUserName());
System.out.println(u2.getUserAge());
System.out.println(u2.getUserGender());
// 해결 방법2 : 매개변수 생성자를 이용해서
// 객체가 생성될 때 부터 다른 값으로 필드를 초기화
User u3 = new User("test3", "password333"); // 매개변수 생성자
System.out.println( u3.getUserId() );
System.out.println( u3.getUserPw() );
}
public void ex4() {
// 매개변수 생성자 예제
User u1 = new User(); // 기본생성자
User u2 = new User("user02", "pass02"); // 매개변수 2개 생성자
User u3 = new User("user03", "pass03", "김길동", 30, '남'); // 매개변수 5개 생성자(전부 초기화)
System.out.printf("u1 : %s / %s / %s / %d / %c\n",
u1.getUserId(), u1.getUserPw(), u1.getUserName(),
u1.getUserAge(), u1.getUserGender() );
System.out.printf("u2 : %s / %s / %s / %d / %c\n",
u2.getUserId(), u2.getUserPw(), u2.getUserName(),
u2.getUserAge(), u2.getUserGender() );
System.out.printf("u3 : %s / %s / %s / %d / %c\n",
u3.getUserId(), u3.getUserPw(), u3.getUserName(),
u3.getUserAge(), u3.getUserGender() );
}
}