Java 개념정리 12일차

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()을 호출하지 않으면 값이 없는 상태로 남을 수 있음
  • 구조가 단순해서 상속·접근제어 연습용으로 적합
  • 실제 프로그램에서는 실수 가능성이 큼
구분1번 방법 (생성자)2번 방법 (메서드 대입)
초기화 시점 객체 생성 시 객체 생성 후
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