클래스는 자바에서 객체를 생성하기 위한 설계도입니다. 객체는 클래스에서 정의된 속성과 기능(메서드)을 실제로 사용할 수 있는 실제 모습(instance)입니다. 자바에서 클래스와 객체를 활용하면 객체지향 프로그래밍의 핵심 개념인 캡슐화(데이터 보호), 상속(재사용), 다형성(다양한 동작)을 쉽게 구현할 수 있습니다.
객체지향 프로그래밍(OOP)은 데이터를 객체라는 단위로 묶어 설계하는 프로그래밍 방식입니다.
데이터와 동작(메서드) 등 프로그램에 필요한 모든 자원을 하나의 객체로 묶고, 외부에서 접근을 제한합니다. 이를 통해 객체의 데이터를 보호하고 외부에서 잘못된 접근을 못하게 막을 수 있습니다.
상속은 한 클래스의 데이터와 기능을 다른 클래스가 이어받는 것을 말합니다. 상속을 통해 클래스끼리 부모-자식 관계가 생깁니다.
기존 클래스를 재사용하여 새로운 클래스를 작성합니다.
동작이나 형태가 다른 기능을 하나의 이름으로 사용할 수 있게 하는 것을 의미합니다.
같은 이름의 메서드나 객체가 다양한 형태로 동작할 수 있습니다. 자바에서는 오버라이딩과 오버로딩 등을 통해 다형성을 지원합니다.
객체의 구체적인 구현을 숨기고, 인터페이스를 통해 필요한 기능만 제공합니다.
객체마다 데이터와 동작을 구체적으로 정의하지 않고 객체들의 공통적인 데이터와 동작만 추출해 선언해두는 것입니다. 이렇게 선언한 클래스를 추상화 클래스라고 합니다.
클래스와 객체를 현실에 빗대어 설명할 때 자동차를 예로 많이 듭니다. 자동차는 설계도를 바탕으로 제작하는데, 이때 설계도가 클래스, 설계도로 구현한 자동차가 객체입니다. 설계도를 기반으로 자동차를 여러 대 만들 수 있듯, 클래스를 기반으로 객체를 여러 개 생성할 수 있습니다.
클래스는 class 키워드를 사용하여 선언합니다.
public class Car {
// 필드
String color;
int speed
// 메서드
void drive() {
System.out.println("The car is driving.");
}
}
클래스에는 '필드, 메서드, 생성자'라는 3가지 구성 요소가 있습니다. 이들을 클래스의 멤버라고 합니다.
1. 인스턴스 변수
public class Person {
String name; // 인스턴스 변수
int age; // 인스턴스 변수
}
public class Main {
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "홍길동"; // 각 객체에서 고유한 값으로 초기화
person1.age = 25; // 각 객체에서 고유한 값으로 초기화
Person person2 = new Person();
person2.name = "윤봉길"; // 각 객체에서 고유한 값으로 초기화
person2.age = "22"; // 각 객체에서 고유한 값으로 초기화
System.out.println(person1.name + "님은 " + person1.age + "살입니다.");
System.out.println(person2.name + "님은 " + person2.age + "살입니다.");
}
}
홍길동님은 25살입니다.
윤봉길님은 22살입니다.
2. 클래스 변수
static 키워드를 사용하여 선언하며, 클래스 로드 시 한 번만 초기화됩니다.public class Calculator {
static double PI = 3.14159; // 클래스 변수
static double calculateCircleArea(double radius) {
return PI * radius * radius; // 원의 넓이 구하기
}
public class Main {
public static void main(String[] args) {
System.out.println("원의 넓이: " + Calculator.calculateCircleArea(10));
}
}
원의 넓이: 314.159
3. 지역 변수
public class Main {
public static void main(String[] args) {
int localVariable = 10;
System.out.println("지역 변수: " + localVariable);
}
}
지역 변수: 10
프로그래밍을 하다 보면 특정 작업을 여러 번 수행해야 할 때가 있습니다. 동일한 작업을 반복적으로 작성하지 않기 위해, 해당 작업을 수행하는 코드를 별도로 정의하고 필요할 때 가져다 쓸 수 있습니다. 이처럼 특정 작업을 수행하는 코드 블록을 함수라고 하며, 자바에서는 클래스 안에 정의한 함수를 메서드라고 부릅니다.
[접근 제한자] 반환형 메서드명(매개변수1, 매개변수2, ...) {
// 메서드 본분
return 반환값; // 반환형이 void가 아닌 경우 반드시 반환값 필요
}
1. 접근 제한자
public, protected, default, private 키워드로 설정 가능합니다.2. 반환형
void로 선언하며, 이 경우 return 문은 생략 가능합니다.3. 메서드명
4. 매개변수
5. 메서드 본문
public class Car {
// 메서드 정의
public void drive() {
System.out.println("The car is driving.");
}
public int add(int a, int b) {
return a + b; // 두 숫자의 합을 반환
}
}
public class Main {
public static void main(String[] args) {
Car car = new Car();
car.drive(); // 출력: The car is driving.
int sum = car.add(5, 15);
System.out.println("Sum: " + sum); // 출력: Sum: 15
}
}
생성자는 클래스의 객체를 생성하고 초기화하는 데 사용되는 특별한 메서드입니다.
클래스의 설계도에 따라 객체를 생성할 때, 필요한 초기값을 설정하거나 초기 작업을 수행하는 역할을 합니다.
객체 생성 시 자동 실행:
클래스 이름과 동일:
반환형 없음:
오버로딩 가능:
명시적 호출:
new 키워드를 사용하여 객체를 생성할 때 호출됩니다.기본 생성자 제공:
public class ClassName {
// 생성자
public ClassName() {
// 초기화 작업
}
}
예제
public class Person {
String name;
int age;
// 생성자
public Person(String name, int age) {
this.name = name; // 초기화 작업
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person("홍길동", 30); // 객체 생성과 초기화
System.out.println(person.name); // 출력: 홍길동
System.out.println(person.age); // 출력: 30
}
}
예제
public class Person {
String name;
int age;
// 기본 생성자
public Person() {
this.name = "Unknown";
this.age = 0;
}
// 매개변수가 있는 생성자
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
Person person1 = new Person(); // 기본 생성자 호출
Person person2 = new Person("홍길동", 30); // 매개변수 있는 생성자 호출
System.out.println(person1.name + ", " + person1.age); // 출력: Unknown, 0
System.out.println(person2.name + ", " + person2.age); // 출력: 홍길동, 30
}
}
예제
public class Car {
String color;
// 기본 생성자를 정의하지 않으면, 컴파일러가 자동으로 추가
}
public class Main {
public static void main(String[] args) {
Car car = new Car(); // 기본 생성자 호출
System.out.println(car.color); // 출력: null (초기화되지 않은 필드)
}
}
this() 키워드를 사용합니다.this()는 같은 클래스 내의 다른 생성자를 호출하는 특별한 문법입니다.this() 키워드에 부여하여, 생성자 간의 코드 재사용을 가능하게 했습니다.예제
public class Person {
String name;
int age;
// 기본 생성자
public Person() {
this("Unknown", 0); // 다른 생성자(매개변수가 있는 생성자) 호출
}
// 매개변수가 있는 생성자
public Person(String name, int age) {
this.name = name; // 전달받은 값을 필드에 저장
this.age = age; // 전달받은 값을 필드에 저장
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person(); // 기본 생성자 호출
System.out.println(person.name + ", " + person.age); // 출력: Unknown, 0
}
}
public, protected, default, private 모두 사용 가능하며, 객체 생성 범위를 제어할 수 있습니다.예제: 생성자의 접근 제한자
public class Singleton {
private static Singleton instance;
// private 생성자
private Singleton() {
}
// getInstance()를 통해 객체 생성
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
this의 기본적인 역할this는 현재 생성된 객체 자기 자신을 참조합니다.
객체의 멤버(필드, 메서드)에 접근할 때 주로 사용됩니다.
주요 역할
필드와 지역 변수 구분
public class Person {
String name;
public Person(String name) {
this.name = name; // this를 사용해 필드와 지역 변수를 구분
}
}
현재 객체의 메서드 호출
public void display() {
System.out.println("Hello from " + this.name);
}
this()의 특별한 역할: 생성자 호출this()는 같은 클래스 내의 다른 생성자를 호출하는 특별한 문법입니다.this() 키워드에 부여하여, 생성자 간의 코드 재사용을 가능하게 했습니다.this()로 생성자를 호출하는 이유this()를 사용하면 해당 작업을 중복해서 작성하지 않아도 됩니다.this()를 사용하면 초기화 작업을 하나의 생성자에 집중시킬 수 있어, 코드 유지보수가 쉬워집니다.this()의 사용 규칙같은 클래스 내의 생성자를 호출
this()는 현재 클래스 내의 다른 생성자를 호출할 때만 사용할 수 있습니다. super()를 사용해야 합니다.생성자 내부에서만 사용 가능
this()는 생성자 내부에서만 사용할 수 있으며, 일반 메서드나 다른 곳에서는 사용할 수 없습니다.생성자의 첫 줄에서만 사용 가능
this()는 반드시 생성자의 첫 번째 줄에서 호출되어야 합니다. 예제
public class Person {
String name;
int age;
// 기본 생성자
public Person() {
this("Unknown", 0); // 다른 생성자를 호출
}
// 매개변수가 있는 생성자
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
this()와 일반 this의 차이this
this()
예제
public class Person {
String name;
// 기본 생성자
public Person() {
this("Unknown"); // this()로 다른 생성자 호출
}
// 매개변수가 있는 생성자
public Person(String name) {
this.name = name; // this로 필드와 지역 변수 구분
}
}
객체는 클래스로부터 new 연산자를 통해 생성됩니다.
new 키워드 뒤에는 객체를 생성할 클래스명이 오고, 뒤에 소괄호와 세미콜론이 붙습니다. 이렇게 하면 해당 클래스에 정의된 생성자가 호출되며 객체가 생성됩니다.
new 클래스명();
객체를 생성한 후에는 메모리의 위치(주소)를 저장하여 사용해야 합니다. 이를 위해 참조 변수를 사용합니다.
객체의 참조 변수를 선언할 때 자료형은 객체를 생성한 클래스명과 동일해야 합니다.
참조 변수에 저장되는 값은 실제 값이 아니라 객체가 저장된 메모리 주소입니다.
클래스명 변수명 = new 클래스명();
public class Car {
// 필드
String color;
int speed;
// 메서드
public void drvie() {
System.out.println("The car is driving.");
}
}
public class Main {
public static void main(String[] args) {
// 객체 생성
Car myCar = new Car(); // Car 클래스의 객체 생성
// 객체 사용
myCar.color = "Green"; // 필드 초기화
myCar.speed = 120; // 필드 초기화
myCar.drive(); // 메서드 호출
}
}
The car is driving.
public class Student {
// 필드
String name;
int age;
// 메서드
void study() {
System.out.println(name + " is studying.");
}
}
public class Main {
public static void main(String[] args) {
// 객체 생성
Student student = new Student(); // 기본 생성자 호출
student.name = "홍길동"; // 필드 초기화
student.age = 20; // 필드 초기화
student.study(); // 메서드 호출
}
}
홍길동 is studying.
static 키워드는 해당 필드나 메서드가 특정 객체가 아니라 클래스 자체에 속하도록 정의합니다.
static 멤버는 객체 생성 없이도 사용 가능합니다.
public class Calculator {
static int add(int a, int b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
int result = Calculator.add(5, 10); // 객체 생성 없이 호출 가능
System.out.println("Result: " + result);
}
}
Result: 15
접근 제한자는 클래스와 클래스 구성 요소에 접근할 수 있는 권한을 나타냅니다.
접근 제한자는 클래스 멤버의 접근 범위를 제어합니다.

protected와 마찬가지로 필드, 메서드, 생성자에만 사용할 수 있습니다.defaut 권한이 적용됩니다. 같은 패키지의 클래스에서만 접근할 수 있고 클래스, 필드, 메서드, 생성자 모두에 사용할 수 있습니다.캡슐화를 구현하기 위해 필드는 보통 private으로 선언하여 외부에서 직접 접근하지 못하도록 보호합니다. 대신, 외부와의 접근은 게터(getter)와 세터(setter) 메서드를 통해 제어합니다.
게터와 세터는 필드 값을 안전하게 읽거나 수정할 수 있는 방법을 제공합니다.
게터 메서드는 private 접근 제한자가 붙은 필드를 외부에서 읽을 수 있게 하는 메서드입니다.
get + 필드명으로 작성하며, 첫 글자는 대문자로 합니다.public String getName() {
return name; // 필드 값을 반환
}
세터 메서드는 private으로 보호된 필드의 값을 외부에서 설정하거나 변경할 수 있도록 하는 메서드입니다.
void입니다.set + 필드명으로 작성하며, 첫 글자는 대문자로 합니다.public String setName(String name) {
this.name = name; // 필드 값을 설정
}
public class student {
// 필드
private String name;
private int age;
// getter
public String getName() {
return name; // 필드 값을 반환
}
public int getAge() {
return age; // 필드 값을 반환
}
// setter
public void setName(String name) {
this.name = name; // 필드 값을 설정
}
public void setAge(int age) {
if (age > 0) { // 유효성 검사
this.age = age;
} else {
System.out.println("나이는 반드시 0 이상이어야 합니다.");
}
}
}
public class Main {
public static void main(String[] args) {
// 객체 생성
Student student = new Student(); // 기본 생성자
// 세터를 사용하여 필드 값 설정
student.setName("홍길동");
student.setAge(20);
// 게터를 사용하여 필드 값 읽기
System.out.println("이름: " + student.getName()); // 출력: 이름: 홍길동
System.out.println("나이: " + student.getAge()); // 출력: 나이: 20
}
}
private으로 선언하여 외부에서 직접 접근을 차단하고, 무분별한 수정으로부터 데이터를 보호합니다.getter만 제공)으로 만들거나, 쓰기 전용으로(setter만 제공) 설정할 수 있습니다.