2026. 1. 15. 09:24ㆍ대우개발원 수업 내용/Java 정리
[final 클래스와 final 메소드]
final 키워드
▪ 해당 선언이 최종 상태이며 수정될 수 없음을 의미
▪ 클래스 및 메소드 선언 시 final 키워드를 사용하면 상속과 관련됨
상속할 수 없는 final 클래스
▪ 부모 클래스가 될 수 없어 자식 클래스 만들 수 없음을 의미
public final class String { ...} 이렇게 썼을때, public class NewString extends String { ... } 은 불가능하다.
재정의할 수 없는 final 메소드
▪ 부모 클래스에 선언된 final 메소드는 자식 클래스에서 재정의 할 수 없음
예시 Car, SportsCar

package sec01;
public class Car {
// 필드
public int speed;
// 메소드
public void speedUp() {
speed += 1;
}
// final 메소드
public final void stop() {
System.out.println("차를 멈춤");
speed = 0;
}
}
package sec01;
public class SportsCar extends Car{
@Override
public void speedUp() {
speed += 10;
}
// @Override // 오버라이딩을 할 수 없음
// public void stop() {
// System.out.println("스포츠카를 멈춤");
// speed = 0;
// }
}
Quiz. Adult.java (class)
클래스 Person 의 필드
• int age; , • public String name; , • protected int height; , • private int weight;
클래스 Adult(실행)
• Person 클래스 상속
• private 인 weight 필드는 getter, setter 생성하여 접근 사용 가능
• 나이, 이름, 키, 몸무게를 호출하는 set()메서드 생성
출력예시:
나이:30
이름:홍길동
키:175
몸무게:99

package sec01;
public class Person {
public int age;
public String name;
protected int height;
private int weight;
// public Person(int age, String name, int height, int weight) {
//1번 방법
// this.age = age;
// this.name = name;
// this.height = height;
// this.weight = weight;
// }
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
package sec01;
public class Adult extends Person{
//1번방법
// public Adult(int age, String name, int height, int weight) {
// super(age, name, height, weight);
// }
void set() {
//2번방법
this.age = 30;
this.name = "홍길동";
this.height = 175;
this.setWeight(99);
//1,2 공통
System.out.println("나이 : " + age);
System.out.println("이름: " + name);
System.out.println("키: " + height);
System.out.println("몸무게: " + getWeight());
}
public static void main(String[] args) {
//1번 방법
// Adult ad = new Adult(30, "홍길동", 175, 99);
//2번 방법
Adult ad = new Adult();
ad.set();
}
}
1번 방법: 생성자 + super()를 이용한 초기화
- Person 클래스에 생성자를 만든다.
- Adult 클래스 생성자에서 super(...)를 호출하여
부모 클래스의 필드를 객체 생성 시점에 한 번에 초기화한다.
특징
- 객체가 생성되는 순간에 모든 값이 확정됨
- 값이 없는 불완전한 객체가 만들어질 가능성이 없음
- 객체의 일관성(안정성) 이 높음
- 실무와 교재에서 권장되는 방식
2번 방법: 기본 생성자 + 필드 직접 대입
- 생성자는 사용하지 않음 (기본 생성자 사용)
- 객체 생성 후, 메서드(set())에서 필드에 값을 직접 대입
특징
- 객체 생성 후에 값을 나중에 설정
- set()을 호출하지 않으면 값이 없는 상태로 남을 수 있음
- 구조가 단순해서 상속·접근제어 연습용으로 적합
- 실제 프로그램에서는 실수 가능성이 큼
| 초기화 시점 | 객체 생성 시 | 객체 생성 후 |
| super() 사용 | 사용함 | 사용 안 함 |
| 객체 안정성 | 높음 | 낮음 |
| 실무 사용 | 많이 사용 | 거의 사용 안 함 |
| 학습 목적 | 객체지향 구조 이해 | 접근제어 연습 |
Quiz. SpellEx.java (class)
마법사가 3가지 주문을 외우는 코드를 작성하시오,
Spell클래스를 상속하는 Fire(), Light(),
Ice() 각 클래스와 메서드 생성
기본 타입과 마찬가지로 클래스도 타입 변환이 있다.
이를 활용하면 객체 지향 프로그래밍의 다형성을 구현할 수 있다.
다형성
▪ 사용 방법은 동일하지만 다양한 객체 활용해 여러 실행결과가 나오도록 하는 성질
▪ 메소드 재정의와 타입 변환으로 구현
[자동 타입 변환]
자동 타입 변환 (promotion)
▪ 프로그램 실행 도중 자동으로 타입 변환 일어나는 것
▪ 바로 위 부모가 아니더라도 상속 계층에서 상위 타입인 경우 자동 타입 변환 일어날 수 있음
package sec01;
class A {
}
class B extends A {
}
class C extends A {
}
class D extends B {
}
class E extends C {
}
public class PromtionEx {
public static void main(String[] args) {
B b = new B( );
C c = new C( );
D d = new D( );
E e = new E( );
A a1 = b; //(가능)
A a2 = c; //(가능)
A a3 = d; //(가능)
A a4 = e; //(가능)
B b1 = d; //(가능)
C c1 = e; //(가능)
B b3 = e; //(불가능)
C c2 = d; //(불가능)
}
}
▪ 부모 타입으로 자동 타입 변환 이후에는 부모 클래스에 선언된 필드 및 메소드만 접근 가능
( 자식 클래스에 있는 메소드는부모 타입으로 자동 타입 변환된 참조 변수로는 호출할 수 없다.)
▪ 예외적으로, 메소드가 자식 클래스에서 재정의될 경우 자식 클래스의 메소드가 대신 호출

package sec01;
public class Parent {
// 메소드 선언
public void method1() {
System.out.println("Parent-method1()");
}
// 메소드 선언
public void method2() {
System.out.println("Parent-method2()");
}
}
package sec01;
public class Child extends Parent {
// 메소드 오버라이딩
@Override
public void method2() {
System.out.println("Parent-method2()");
}
// 메소드 선언
public void method3() {
System.out.println("Parent-method3()");
}
}
package sec01;
public class ChildEx {
public static void main(String[] args) {
// 자식 객체 생성
Child child = new Child();
// 자동 타입 변환
Parent parent = child;
// 메소드 호출
parent.method1();
parent.method2();
// parent.method3();//호출 불가능
}
}

package sec01;
public class Parent {
// 필드 선언
public String field1;
// 메소드 선언
public void method1() {
System.out.println("Parent-method1()");
}
// 메소드 선언
public void method2() {
System.out.println("Parent-method2()");
}
}
package sec01;
public class Child extends Parent {
// 필드 선언
public String field2;
// 메소드 오버라이딩
@Override
public void method2() {
System.out.println("Parent-method2()");
}
// 메소드 선언
public void method3() {
System.out.println("Parent-method3()");
}
}
package sec01;
public class ChildEx {
public static void main(String[] args) {
// 자식 객체 생성
Child child = new Child();
// 자동 타입 변환
Parent parent = child;
// Parent parent = new Parent();
// Parent 타입으로 필드와 메소드 사용
parent.field1 = "deta1";
// Parent.field2 = "data2;" //(field2에 접근이 불가능)
// 메소드 호출
parent.method1();
parent.method2();
// parent.method3();//호출 불가능
// 강제 타입 변환
Child child1 = (Child) parent;
// Child 타입으로 필드와 메소드 사용
child.field1 = " data2"; //(가능)
child.method3(); //(가능)
}
}
[필드의 다형성]
▪ 필드 타입을 부모 타입으로 선언할 경우
• 다양한 자식 객체가 저장되어 필드 사용 결과 달라질 수 있음
위의 내용을 포함한 예제 코드

package sec02;
public class Tire {
//필드
public int maxRotation;
public int accumulatedRotation;
public String location;
// 생성자
public Tire(String location, int maxRotataion) {
this.location = location;
this.maxRotation = maxRotataion;
}
// // 메소드 선언
// public void roll() {
// System.out.println("회전합니다.");
// }
public boolean roll() {
++accumulatedRotation;
if(accumulatedRotation<maxRotation) {
System.out.println(location + "Tire 수명" +
(maxRotation-accumulatedRotation) + "회");
return true;
} else {
System.out.println("*** " + location + "Tire 펑크 ***");
return false;
}
}
}
package sec02;
public class Car {
// // 필드 선언
// public Tire tire;
Tire frontLestTire = new Tire("앞왼쪽" , 6);
Tire frontRightTire = new Tire("앞오른쪽", 2);
Tire backLeftTire = new Tire("뒤왼쪽" , 3);
Tire backRightTire = new Tire("뒤오른쪽", 4);
// // 메소드 선언
// public void run() {
// // tire 핃드에 대입된 객체의 roll 메소드 호출
// tire.roll();
// }
int run() {
System.out.println("[자동차가 달립니다.]");
if(frontLestTire.roll()==false) { stop(); return 1; } ;
if(frontRightTire.roll()==false) { stop(); return 2; } ;
if(backLeftTire.roll()==false) { stop(); return 3; } ;
if(backRightTire.roll()==false) { stop(); return 4; } ;
return 0;
}
void stop() {
System.out.println("[자동차가 멈춥니다.]");
}
}
package sec02;
public class CarEx {
public static void main(String[] args) {
// // Car 객체 생성
// Car myCar = new Car();
//
// // Tire 객체 장착
// myCar.tire = new Tire();
// myCar.run();
//
//// HankookTire 객체 장착
// myCar.tire = new HankookTire();
// myCar.run();
//
//// KumhoTire 객체 장착
// myCar.tire = new KumhoTire();
// myCar.run();
//
//
// }
Car car = new Car();
for(int i=1; i <= 5 ; i++) {
int problemLocation = car.run();
switch(problemLocation) {
case 1:
System.out.println("앞 왼쪽 HankookTire로 교체");
car.frontLestTire = new HankookTire("앞왼쪽", 15);
break;
case 2:
System.out.println("앞 왼쪽 KumhoTire로 교체");
car.frontRightTire = new KumhoTire("앞오른쪽", 13);
break;
case 3:
System.out.println("뒤왼쪽 HankookTire로 교체");
car.backLeftTire = new HankookTire("뒤왼쪽", 14);
break;
case 4:
System.out.println("뒤오른쪽 KumhoTire로 교체");
car.backRightTire = new KumhoTire("뒤오른쪽", 17);
break;
}
System.out.println("------------------------------------------------");
}
}
}
package sec02;
public class HankookTire extends Tire {
//필드
//생성자
public HankookTire(String location, int maxRotataion) {
super(location, maxRotataion);
}
// // 메소드 재정의(오버라이딩)
// @Override
// public void roll() {
// System.out.println("한국 타이거가 회전합니다.");
// }
public boolean roll() {
++accumulatedRotation;
if(accumulatedRotation<maxRotation) {
System.out.println(location + "HankookTire 수명" +
(maxRotation-accumulatedRotation) + "회");
return true;
} else {
System.out.println("*** " + location + "HankookTire 펑크 ***");
return false;
}
}
}
package sec02;
public class KumhoTire extends Tire{
//필드
//생성자
public KumhoTire(String location, int maxRotataion) {
super(location, maxRotataion);
}
// // 메소드 재정의
// public void roll() {
// System.out.println("금호 타이거가 회전합니다.");
// }
public boolean roll() {
++accumulatedRotation;
if(accumulatedRotation<maxRotation) {
System.out.println(location + "KumhoTire 수명" +
(maxRotation-accumulatedRotation) + "회");
return true;
} else {
System.out.println("*** " + location + "KumhoTire 펑크 ***");
return false;
}
}
}
출력결과
[자동차가 달립니다.]
앞왼쪽Tire 수명5회
앞오른쪽Tire 수명1회
뒤왼쪽Tire 수명2회
뒤오른쪽Tire 수명3회
------------------------------------------------
[자동차가 달립니다.]
앞왼쪽Tire 수명4회
*** 앞오른쪽Tire 펑크 ***
[자동차가 멈춥니다.]
앞 왼쪽 KumhoTire로 교체
------------------------------------------------
[자동차가 달립니다.]
앞왼쪽Tire 수명3회
앞오른쪽KumhoTire 수명12회
뒤왼쪽Tire 수명1회
뒤오른쪽Tire 수명2회
------------------------------------------------
[자동차가 달립니다.]
앞왼쪽Tire 수명2회
앞오른쪽KumhoTire 수명11회
*** 뒤왼쪽Tire 펑크 ***
[자동차가 멈춥니다.]
뒤왼쪽 HankookTire로 교체
------------------------------------------------
[자동차가 달립니다.]
앞왼쪽Tire 수명1회
앞오른쪽KumhoTire 수명10회
뒤왼쪽HankookTire 수명13회
뒤오른쪽Tire 수명1회
------------------------------------------------
[매개 변수의 다형성]
▪ 매개 변수를 부모 타입으로 선언하는 효과
• 메소드 호출 시 매개값으로 부모 객체 및 모든 자식 객체를 제공할 수 있음
• 자식의 재정의된 메소드가 호출 -> 다형성
예제 코드
[강제 타입 변환]
강제 타입 변환 (casting)
▪ 부모 타입을 자식 타입으로 변환
• 조건: 자식 타입이 부모 타입으로 자동 타입 변환한 후 다시 반대로 변환할 때 사용
[객체 타입 확인]
instanceof 연산자
▪ 어떤 객체가 어느 클래스의 인스턴스인지 확인
▪ 메소드 내 강제 타입 변환 필요한 경우
• 타입 확인하지 않고 강제 타입 변환 시도 시 ClassCastException 발생할 수 있음
• instanceof 연산자 통해 확인 후 안전하게 실행
예시 ) boolean result = 좌항(객체) instanceof 우항(타입)
예제 코드

package sec01;
public class Child extends Parent {
// 필드 선언
public String field2;
// 메소드 오버라이딩
@Override
public void method2() {
System.out.println("Parent-method2()");
}
// 메소드 선언
public void method3() {
System.out.println("Parent-method3()");
}
}
package sec01;
public class Parent {
// 필드 선언
public String field1;
// 메소드 선언
public void method1() {
System.out.println("Parent-method1()");
}
// 메소드 선언
public void method2() {
System.out.println("Parent-method2()");
}
}
package sec01;
public class InstanceofEx {
public static void method1(Parent parent) {
if(parent instanceof Child) {
Child child = (Child) parent;
System.out.println("method1 - Child로 변환 성공");
} else {
System.out.println("method1 - Child로 변환되지 않음");
}
}
public static void method2(Parent parent) {
Child child = (Child) parent;
System.out.println("method2 - Child로 변환 성공");
}
public static void main(String[] args) {
Parent parentA = new Child();
method1(parentA);
method2(parentA);
Parent parentB = new Parent();
method1(parentB);
method2(parentB); //예외 발생
}
}
Quiz. PersonEx.java (class)
클래스 Person 의 필드
• String phone;
• Phone에 대해 getter, setter 구성
클래스 Professor
• Person 클래스 상속
• 메서드 생성하여 아래와 같이 호출
출력예시)
Professor :010-111-1222 // Professor의 객체
Professor :010-111-1222 // Person의 객체를 타입변환하여 호출

package quiz2;
public class Person {
public String phone;
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
package quiz2;
public class Professor extends Person{
@Override
public String getPhone(){
return "Professor :" + super.getPhone();
}
}
package quiz2;
public class PersonEx {
public static void main(String[] args) {
Professor p = new Professor();
p.setPhone("010-111-1222");
System.out.println(p.getPhone());
Person a = p;
System.out.println(a.getPhone());
}
}
quiz.racer 레이서를 불러 자동차 운전하는 코드
매개변수 다형성 예시 코드
Shape예제 코드

package sec03.shape;
public class Shape { // 도형의 슈퍼 클래스
public void draw() {
System.out.println("Shape");
}
}
class Line extends Shape {
public void draw() { // 메소드 오버라이딩
System.out.println("Line");
}
}
class Rect extends Shape {
public void draw() { // 메소드 오버라이딩
System.out.println("Rect");
}
}
class Circle extends Shape {
public void draw() { // 메소드 오버라이딩
System.out.println("Circle");
}
}
package sec03.shape;
import sec03.shape.Shape.Line;
import sec03.shape.Shape.Rect;
import sec03.shape.Shape.Circle;;
public class ShapeEx {
static void paint(Shape p) { // Shape를 상속받은 객체들이
// 매개변수로 넘어올 수 있음
p.draw(); // p가 가리키는 객체에 오버라이딩된 draw() 호출.
// 돟적 바인딩
}
public static void main(String[] args) {
Line line = new Line();
paint(line); // Line의 draw()실행. "Line" 출력
paint(new Shape()); // Shape의 draw() 실행. "Shape"출력
paint(new Line()); // 오버라이딩된 메소드 Line의 draw()실행
paint(new Rect()); // 오버라이딩된 메소드 Rect의 draw()실행
paint(new Circle()); // 오버라이딩된 메소드 Circle의 draw()실행
}
}
quiz .스케쥴러를 작성
* 일정을 출력하는 스케쥴러를 작성해봅시다.
부모클래스 (Event.java)
// OneDay/Duration/Deadlined Event의 공통 멤버를
관리하는 상위 클래스
public String title;
public Event(String title) {
this.title = title;
}
메인 클래스 (scheduler.java)
public static void main(String[] args) {
Event[] evt = new Event[3];
myDate date1 = new myDate(2021,6,17);
myDate date2 = new myDate(2021,6,04);
myDate date3 = new myDate(2021,8,30);
evt[0] = new OneDay("오늘",date1);
evt[1] = new Duration("java",date2,date3);
evt[2] = new Deadlined("마감날짜",date3);
for(int i=0; i<evt.length;i++) {
System.out.println( "일 정: "+ evt[i].toString());
}
}
자식 클래스
OneDay 클래스
필드 : title(상속), myDate date
생성자 : 매개변수 2개
메서드 : toString
Duration 클래스
필드 : title(상속), myDate begin, myDate end
생성자 : 매개변수 3개
메서드 : toString
Deadlined 클래스
필드 : title(상속), myDate deadline
생성자 : 매개변수 2개
메서드 : toString
myDate 클래스
필드 : int year, month, day
생성자 : 매개변수 3개
메서드 : toString
답 ↓
실행코드
package quiz.scheduler;
public class Deadlined extends Event {
public MyDate deadline;
public Deadlined(String title, MyDate deadline) {
super(title);
this.deadline = deadline;
}
public String tosString() {
return title + ", " + "~" + deadline.toString();
}
}
package quiz.scheduler;
public class MyDate {
int year;
int month;
int day;
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public String toString() {
return year + "/" + month + "/" + day;
}
}
package quiz.scheduler;
public class Event {
public String title;
public Event(String title) {
this.title = title;
}
}
package quiz.scheduler;
public class Duration extends Event {
public MyDate begin;
public MyDate end;
public Duration(String title, MyDate begin, MyDate end) {
super(title);
this.begin = begin;
this.end = end;
}
public String toString() {
return title + "," + "시작 날짜: " + begin.toString() +
", 마감날짜: " + end.toString();
}
}
package quiz.scheduler;
public class OneDay extends Event {
public MyDate date;
public OneDay(String title , MyDate date) {
super(title);
this.date = date;
}
public String toString() {
return title + "," + date.toString();
}
}
package quiz.scheduler;
public class Scheduler {
public static void main(String[] args) {
Event[] evt = new Event[3];
MyDate date1 = new MyDate(2021,6,17);
MyDate date2 = new MyDate(2021,6,04);
MyDate date3 = new MyDate(2021,8,30);
evt[0] = new OneDay("오늘",date1);
evt[1] = new Duration("java",date2,date3);
evt[2] = new Deadlined("마감날짜",date3);
for(int i=0; i<evt.length;i++) {
System.out.println( "일 정: "+ evt[i].toString());
}
}
}
'대우개발원 수업 내용 > Java 정리' 카테고리의 다른 글
| Java 개념정리 14일차 (0) | 2026.01.19 |
|---|---|
| Java 개념 정리 13일차 (1) | 2026.01.15 |
| Java 개념정리 11일차 (1) | 2026.01.13 |
| Java 개념정리 10일차 (1) | 2026.01.12 |
| Java 개념정리 9일차 (1) | 2026.01.12 |






