1. 클래스와 객체란?
클래스는 동일한 속성과 행동을 가진 객체들의 추상적 집합이며, 객체는 클래스의 인스턴스로 상태와 행동을 가진다.
2. 자바에서 클래스와 객체의 구조는 어떻게 되나요?
class Person {
// 필드는 클래스의 속성
String fullName = "장삼";
int years = 23;
// 메서드는 클래스의 행동
public void studyJava(){
System.out.println("자바 공부");
}
public void eat(){
System.out.println("식사");
}
}
public class TestPerson{
public static void main(String[] args) {
// 객체 생성
Person person = new Person();
// 필드 접근
System.out.println(person.fullName);
System.out.println(person.years);
person.fullName = "이사";
person.years = 24;
// 메서드 호출
person.studyJava();
person.eat();
}
}
3. 단일 객체 또는 두 객체의 메모리 구조는?
- 스택 메모리: 지역 변수(예: stu1, stu2)와 메서드 호출 저장, 힙에 있는 객체의 주소 참조 저장
- 힙 메모리: 실제 객체(필드 name, age) 저장, 각 객체는 독립적인 메모리 공간
- 메서드 영역: 클래스 정보와 메서드 바이트코드 저장, 객체는 참조 주소를 통해 공유된 메서드 정의 사용
결론: 스택은 힙에 있는 객체를 가리키고, 힙은 고유한 필드를 저장, 메서드 영역은 공유된 메서드 정의를 저장.
4. this 키워드의 역할은?
현재 객체의 생성자, 필드, 메서드 호출 가능
현재 클래스 객체의 참조, 어떤 객체가 this를 호출하면 해당 객체를 가리킴
this() 현재 객체의 기본 생성자 호출, 생성자 내에서만 가능
this(인자) 현재 객체의 매개변수 생성자 호출, 생성자 내에서만 가능
this.필드명
this.메서드명()
필드와 지역변수 이름이 겹칠 경우 "가까운 원칙" 적용
this와 super는 생성자에서 동시에 사용 불가
5. 메모리 내부 표현
필드는 힙에, 지역변수는 스택에 저장
6. super 키워드의 역할은?
부모 클래스의 속성, 메서드, 생성자 접근
super() 부모 클래스 기본 생성자 호출
super(인자) 부모 클래스 매개변수 생성자 호출
super.필드명
super.메서드명()
7. static 키워드의 역할은?
1. 사용법:
a. 필드 수정: static 데이터형 필드명
b. 메서드 수정:
수정자 static 반환형 메서드명(매개변수){
메서드 몸통
return 결과
}
c. 코드 블록 수정: 정적 코드 블록, 클래스 로딩 시 실행
d. 클래스 수정: 내부 클래스만 static으로 수정, 이 경우 정적 내부 클래스가 됨
2. 호출법:
클래스명.정적필드명
클래스명.정적메서드명
8. static의 특징은?
정적 멤버는 클래스 멤버로, 객체보다 먼저 존재하며 클래스 로딩 시 로딩됨
정적 멤버는 동일한 클래스로 생성된 모든 객체가 공유
9. static으로 수정된 필드의 접근 특징
1. 정적 메서드에서 비정적 필드 직접 접근 가능? 불가능
new 객체로 접근
2. 정적 메서드에서 정적 필드 직접 접근 가능? 가능
동일한 클래스 -> 직접 호출
다른 클래스 -> 클래스명으로 호출
3. 비정적 메서드에서 정적 필드 직접 접근 가능? 가능
동일한 클래스 -> 직접 호출
다른 클래스 -> 클래스명으로 호출
4. 비정적 메서드에서 비정적 필드 직접 접근 가능? 가능
동일한 클래스 -> 직접 호출
다른 클래스 -> new 객체로 호출
5. 정적 사용 시기: 도구 클래스 추출 시 일반적으로 정적 사용
10. final 키워드의 역할은?
final로 수정된 속성은 상수
기본형: 값 변경 불가
참조형: 주소 변경 불가, 주소 내 내용(속성)은 변경 가능
11. final 사용 시 주의사항?
final로 수정된 메서드는 자식 클래스에서 재정의 불가, abstract와 함께 사용 불가
final로 수정된 클래스는 상속 불가, String 클래스는 final로 수정됨
final로 수정된 객체, 주소값 변경 불가, 속성값은 변경 가능
final로 수정된 필드, 두 번째 할당 불가, 수동 할당 필요
final로 수정된 지역변수, 두 번째 할당 불가
12. 다형성의 정의는?
동일한 행동(메서드)이 여러 가지 형태로 나타나는 능력
13. 객체 지향 3대 특성은?
캡슐화, 상속, 다형성
14. 캡슐화의 정의는?
세부 사항을 숨기고, 외부에 공개된 인터페이스를 제공하여 세부 사항에 간접 접근 가능
1. private로 필드 수정(세부 사항 숨기기)
2. getXXX/setXXX 메서드 제공(공개된 인터페이스)
a.setXXX: 속성에 값 할당
b.getXXX: 속성 값 조회
15. 자식 클래스는 부모 클래스의 무엇을 상속하나요?
public과 protected로 수정된 속성과 메서드, 동일 패키지 여부와 무관
기본 권한 수정자로 수정된 속성과 메서드, 동일 패키지일 경우 상속
생성자 상속 불가, 자바는 단일 상속만 지원
16. 자식 클래스 상속 후 주의사항?
필요한 필드가 없을 경우 부모 클래스 찾기
자식 객체 생성 시 부모 기본 생성자 먼저 호출
17. 업캐스팅의 정의는?
부모 참조가 자식 객체를 가리키는 경우, 부모 참조로 자식 재정의 및 상속 메서드 접근 가능, 자식 고유 메서드 접근 불가
세 가지 경우
1. 부모 클래스를 매개변수로, 자식 클래스를 인자로
2. 부모 클래스를 반환형으로, 실제 반환값은 자식 클래스
3. 부모 클래스 타입의 배열/컬렉션, 요소는 자식 클래스
// 부모 클래스
class Animal {
public void makeSound() {
System.out.println("동물 소리");
}
}
// 자식 클래스
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("멍멍");
}
// 자식 고유 메서드
public void fetch() {
System.out.println("개가 공을 줍다");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("야옹");
}
// 자식 고유 메서드
public void climbTree() {
System.out.println("고양이 나무 오르기");
}
}
//1. 부모 클래스를 매개변수로, 자식 클래스를 인자로
public class UpCastExample {
// 매개변수는 부모 타입, 인자는 자식 타입 가능
public static void animalSound(Animal animal) {
// Animal 클래스에서 정의된 메서드만 호출 가능
animal.makeSound();
}
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
// 업캐스팅: 부모 참조가 자식 객체를 가리킴
animalSound(dog); // 출력: 멍멍
animalSound(cat); // 출력: 야옹
// 직접 자식 객체 전달 가능
Animal animal = new Dog(); // 업캐스팅
animalSound(animal); // 출력: 멍멍
}
}
// 부모 클래스
class Vehicle {
public void drive() {
System.out.println("차량 이동");
}
}
// 자식 클래스1
class Car extends Vehicle {
@Override
public void drive() {
System.out.println("자동차 이동");
}
public void playMusic() {
System.out.println("자동차 음악 재생");
}
}
// 자식 클래스2
class Bike extends Vehicle {
@Override
public void drive() {
System.out.println("자전거 이동");
}
public void ringBell() {
System.out.println("자전거 벨 울리기");
}
}
class VehicleFactory {
// 타입에 따라 다른 자식 객체 반환, 선언은 부모 타입
public static Vehicle getVehicle(String type) {
if ("car".equalsIgnoreCase(type)) {
return new Car(); // 실제 Car 객체, Vehicle으로 업캐스팅
} else if ("bike".equalsIgnoreCase(type)) {
return new Bike(); // 실제 Bike 객체, Vehicle으로 업캐스팅
} else {
return new Vehicle();
}
}
}
public class UpCastExample2 {
public static void main(String[] args) {
// 메서드 선언 반환은 Vehicle, 실제 반환은 Car 객체(업캐스팅)
Vehicle vehicle1 = VehicleFactory.getVehicle("car");
vehicle1.drive(); // 출력: 자동차 이동
// 메서드 선언 반환은 Vehicle, 실제 반환은 Bike 객체(업캐스팅)
Vehicle vehicle2 = VehicleFactory.getVehicle("bike");
vehicle2.drive(); // 출력: 자전거 이동
}
}
// 부모 클래스
class Employee {
private String name;
public Employee(String name) {
this.name = name;
}
public void work() {
System.out.println(name + " 작업 중");
}
public String getName() {
return name;
}
}
// 자식 클래스1
class Manager extends Employee {
public Manager(String name) {
super(name);
}
@Override
public void work() {
System.out.println(getName() + " 팀 관리");
}
// 자식 고유 메서드
public void holdMeeting() {
System.out.println(getName() + " 회의 진행");
}
}
// 자식 클래스2
class Developer extends Employee {
private String programmingLanguage;
public Developer(String name, String language) {
super(name);
this.programmingLanguage = language;
}
@Override
public void work() {
System.out.println(getName() + " " + programmingLanguage + " 개발");
}
// 자식 고유 메서드
public void debug() {
System.out.println(getName() + " " + programmingLanguage + " 디버깅");
}
}
// 자식 클래스3
class Designer extends Employee {
public Designer(String name) {
super(name);
}
@Override
public void work() {
System.out.println(getName() + " UI 디자인");
}
// 자식 고유 메서드
public void drawPrototype() {
System.out.println(getName() + " 프로토타입 작성");
}
}
public class UpCastExample3 {
public static void main(String[] args) {
// 예제3-1: 부모 타입 배열, 요소는 자식 타입
Employee[] employees = new Employee[4];
// 업캐스팅: 부모 참조가 자식 객체를 가리킴
employees[0] = new Manager("장삼");
employees[1] = new Developer("이사", "Java");
employees[2] = new Designer("왕오");
employees[3] = new Developer("조육", "Python");
System.out.println("=== 배열 예시 ===");
for (Employee emp : employees) {
// 다형성: 실제 객체 타입에 따라 적절한 메서드 호출
emp.work();
// 자식 고유 메서드 직접 호출 불가
// emp.holdMeeting(); // 컴파일 오류
}
// 예제3-2: 부모 타입 컬렉션, 요소는 자식 타입
System.out.println("\n=== 컬렉션 예시 ===");
List<Employee> employeeList = new ArrayList<>();
// 업캐스팅: 컬렉션에 자식 객체 추가
employeeList.add(new Manager("장 매니저"));
employeeList.add(new Developer("이 개발자", "C++"));
employeeList.add(new Designer("왕 디자이너"));
employeeList.add(new Developer("류 프로그래머", "JavaScript"));
// 컬렉션 순회, 다양한 종류의 직원 처리
for (Employee emp : employeeList) {
// 다형성: 실제 객체 타입에 따라 적절한 메서드 호출
emp.work();
}
}
}
18. 다운캐스팅의 정의는?
자식 객체를 가리키는 부모 참조를 자식 타입으로 변환
부모 타입 매개변수를 통해 자식의 속성 또는 메서드 접근 가능
Pet pet = new Dog(); // 먼저 업캐스팅
Dog dog = (Dog)pet; // 다음 다운캐스팅
dog.playFlyDisc(); // 마지막으로 자식 메서드 사용
부모 참조가 자식 객체를 가리킴 -> Pet pet = new Dog();
등호 왼쪽이 누구인지 확인, 해당 클래스의 멤버 변수 호출
new가 누구인지 확인, 해당 클래스의 메서드 호출, 없으면 부모 클래스 탐색
package class5;
// 부모 클래스
class Pet {
String name = "동물";
String type = "Pet 클래스";
public void eat() {
System.out.println(name + " 식사 중");
}
public void sleep() {
System.out.println(name + " 잠자리");
}
public void showType() {
System.out.println("타입: " + type);
}
}
// 자식 클래스1
class Dog extends Pet {
String name = "개"; // 부모의 name 속성 숨기기
String type = "Dog 클래스"; // 부모의 type 속성 숨기기
String breed = "골든 리트리버"; // 자식 고유 속성
@Override
public void eat() {
System.out.println(name + " 사료 먹기");
}
@Override
public void sleep() {
System.out.println("개가 쿨쿨");
}
// 자식 고유 메서드
public void playFlyDisc() {
System.out.println(name + " 플라이디스크 놀기");
}
public void bark() {
System.out.println("와우!");
}
@Override
public void showType() {
System.out.println("개 타입: " + type + ", 품종: " + breed);
}
}
public class DownCastExample {
public static void main(String[] args) {
Pet pet = new Dog(); // 먼저 업캐스팅
pet.showType(); // new된 객체의 메서드 먼저 호출
Dog dog = (Dog)pet; // 다음 다운캐스팅
dog.bark(); // 자식 고유 메서드 호출
dog.playFlyDisc(); // 마지막으로 자식 메서드 사용
// 등호 왼쪽이 누구인지 확인, 해당 클래스의 멤버 변수 호출
System.out.println(pet.name); // 동물
System.out.println(dog.name); // 개
System.out.println(dog.breed); // 골든 리트리버
}
}
19. 부모 클래스 타입 확인 방법은?
객체명 instanceof 클래스명
20. 부모 클래스의 private 필드에 값을 어떻게 할당?
set 메서드를 통해 할당
상속 클래스.setName(name)
상속 생성자에서
super(name);
생성자 보조 사용