Leveraging Programming Languages: Java Lang.

m_ngyeong·2025년 4월 8일
0

정보처리기사 이론

목록 보기
35/36
post-thumbnail

10. Leveraging Programming Languages


Java Lang.

✅ 오버라이딩

class A {
    void print() {
        System.out.println("A");
    }
}

class B extends A {
    void print() {
        System.out.println("B");
    }
}

public class Main {
    public static void main(String[] args) {
        A obj = new B();
        obj.print();
    }
}

🖍️ B

  • obj.print(); → B의 print()

✅ 오버로딩

class Calc {
    int add(int a, int b) {
        return a + b;
    }

    double add(double a, double b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        Calc c = new Calc();
        System.out.println(c.add(2, 3));
        System.out.println(c.add(2.5, 1.5));
    }
}

🖍️
5
4.0

  • c.add(2, 3)int add(int a, int b){} → 5
  • c.add(2.5, 1.5)double add(double a, double b){} → 4.0

✅ equals() vs ==

public class Main {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("hello");
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));
    }
}

🖍️
false
true

  • s1 == s2 → false (다른 객체)
  • s1.equals(s2) → true (내용 비교)

✅ 업캐스팅과 다형성

class Animal {
    void sound() {
        System.out.println("Some sound");
    }
}

class Dog extends Animal {
    void sound() {
        System.out.println("Bark");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Dog();
        a.sound();
    }
}

🖍️ Bark

  • Animal a = new Dog();
  • a.sound(); → Dog의 오버라이딩된 메서드 호출됨 → "Bark"

✅ static 메서드 하이딩

class Parent {
    static void greet() {
        System.out.println("Hello from Parent");
    }
}

class Child extends Parent {
    static void greet() {
        System.out.println("Hello from Child");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent p = new Child();
        p.greet();
    }
}

🖍️ Hello from Parent

  • Parent p = new Child();
  • p.greet();static은 클래스 타입 기준 → "Hello from Parent"

✅ 추상 클래스와 구현

abstract class Shape {
    abstract void draw();
}

class Circle extends Shape {
    void draw() {
        System.out.println("Draw Circle");
    }
}

public class Main {
    public static void main(String[] args) {
        Shape s = new Circle();
        s.draw();
    }
}

🖍️ Draw Circle

  • Shape s = new Circle();
  • s.draw(); → "Draw Circle"

❌ 생성자 실행 순서

class Super {
    Super() {
        System.out.println("Super constructor");
    }
}

class Sub extends Super {
    Sub() {
        System.out.println("Sub constructor");
    }
}

public class Main {
    public static void main(String[] args) {
        Sub obj = new Sub();
    }
}

🖍️
Super constructor
Sub constructor

  • Sub 객체 생성 시 → Super → Sub 순으로 호출됨

❌ instanceof 연산자

class Animal {}
class Cat extends Animal {}

public class Main {
    public static void main(String[] args) {
        Animal a = new Cat();
        System.out.println(a instanceof Animal);
        System.out.println(a instanceof Cat);
    }
}

🖍️
true
true

  • Animal a = new Cat();
  • a instanceof Animal → true
  • a instanceof Cat → true

✅ 변수 하이딩

class Parent {
    int x = 10;
}

class Child extends Parent {
    int x = 20;
}

public class Main {
    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.x);
    }
}

🖍️ 10

  • Parent p = new Child();
  • p.x → 10 (Parent 기준으로 접근됨)

✅ 인터페이스와 다형성

interface Drawable {
    void draw();
}

class Rectangle implements Drawable {
    public void draw() {
        System.out.println("Drawing Rectangle");
    }
}

public class Main {
    public static void main(String[] args) {
        Drawable d = new Rectangle();
        d.draw();
    }
}

🖍️ Drawing Rectangle


instanceof

  • instanceof실제 객체 기준으로 판별한다(타입 일치 여부)
  • instanceof null → 항상 false
  • 인터페이스도 instanceof 가능
  • 클래스끼리는 상속 관계가 아닌 경우 false

❌ 업캐스팅 후 instanceof

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

public class Main {
    public static void main(String[] args) {
        Animal a = new Dog();
        System.out.println(a instanceof Dog);
        System.out.println(a instanceof Cat);
        System.out.println(a instanceof Animal);
    }
}

🖍️
true
false
true

  • a는 실제로 Dog 객체 → instanceof Dog → true
  • aCat은 아님 → instanceof Cat → false
  • DogAnimal을 상속 → instanceof Animal → true

❌ 인터페이스 instanceof

interface Eater {}
class Human implements Eater {}
class Robot {}  // Robot은 Object를 상속하고 있음

public class Main {
    public static void main(String[] args) {
        Object obj = new Human();
        System.out.println(obj instanceof Eater);
        System.out.println(obj instanceof Human);
        System.out.println(obj instanceof Robot);
    }
}

🖍️
true
true
false

  • HumanEater 구현 → instanceof Eater → true
  • objHuman이므로 instanceof Human → true
  • HumanRobot 아님 → false
    new Robot() instanceof Object // true
    Object obj = new Human();obj는 실제로 Human 객체
    HumanRobot은 아무 관계 없음

❌ null 객체에 instanceof

class A {}
public class Main {
    public static void main(String[] args) {
        A a = null;
        System.out.println(a instanceof A);
    }
}

🖍️ false

  • instanceofnull이면 무조건 false
  • 타입과 상관없음

다형성 & 타입 캐스팅 문제

✅ 업캐스팅과 메서드 호출

class Animal {
    void speak() {
        System.out.println("Animal speaks");
    }
}

class Cat extends Animal {
    void speak() {
        System.out.println("Meow");
    }

    void jump() {
        System.out.println("Cat jumps");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Cat();
        a.speak();
        // a.jump();  // 컴파일 에러 발생 여부?
    }
}

🖍️ Meow

  • Animal a = new Cat();
    a.speak();: Cat의 오버라이딩된 메서드 호출
  • a.jump();: a.jump() 는 업캐스팅된 참조로는 불가 → 컴파일 에러

✅ 다운캐스팅

class Parent {
    void show() {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    void show() {
        System.out.println("Child");
    }

    void onlyChild() {
        System.out.println("Child specific method");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent p = new Child(); // 업캐스팅
        p.show();			    // 오버라이딩된 Child.show()

        Child c = (Child) p;    // 다운캐스팅 (정상)
        c.onlyChild();			// Child의 전용 메서드
    }
}

🖍️
Child
Child specific method

❌ 잘못된 다운캐스팅

class A {}
class B extends A {}
class C extends A {}

public class Main {
    public static void main(String[] args) {
        A obj = new C();  // 실제로는 C 타입
        B b = (B) obj;    // C는 B의 하위 클래스 아님 → ClassCastException 발생
        System.out.println("Cast success");
    }
}

🖍️ ❗ 런타임 에러 (ClassCastException) 발생

Exception in thread "main" java.lang.ClassCastException: C cannot be cast to B

✅ 다형성과 배열

class Vehicle {
    void run() {
        System.out.println("Vehicle runs");
    }
}

class Bike extends Vehicle {
    void run() {
        System.out.println("Bike runs fast");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle[] list = { new Vehicle(), new Bike() };
        for (Vehicle v : list) {
            v.run();
        }
    }
}

🖍️
Vehicle runs
Bike runs fast

배열 선언:

Vehicle[] list = { new Vehicle(), new Bike() };
  • list는 Vehicle 타입의 배열이지만,
    그 안에는 Vehicle 객체와 업캐스팅된 Bike 객체가 있음.
  • 즉, 내부적으로는 이렇게 저장돼 있음:
list[0]new Vehicle()
list[1]new Bike()BikeVehicle로 업캐스팅됨

반복문 실행:

for (Vehicle v : list) {
    v.run();
}
  • 첫 번째 반복: v = new Vehicle()v.run() → Vehicle runs
  • 두 번째 반복: v = new Bike()
    v는 Vehicle 타입으로 보이지만, 실제 객체는 Bike이므로
    → 오버라이딩된 Bike.run()이 호출됨
    → Bike runs fast

❌ instanceof를 활용한 안전한 캐스팅

class Animal {}
class Dog extends Animal {
    void bark() {
        System.out.println("Woof");
    }
}

class Cat extends Animal {}

public class Main {
    public static void main(String[] args) {
        Animal a = new Cat();

        if (a instanceof Dog) {
            Dog d = (Dog) a;
            d.bark();
        } else {
            System.out.println("Not a Dog");
        }
    }
}

🖍️ Not a Dog

  • aCat이므로 instanceof Dog → false
    → else 블록 실행됨

✅ 정적 메서드(hiding) vs 인스턴스 메서드(오버라이딩)

class Base {
    static void greet() {
        System.out.println("Hello from Base");
    }

    void say() {
        System.out.println("Base says hi");
    }
}

class Derived extends Base {
    static void greet() {
        System.out.println("Hello from Derived");
    }

    void say() {
        System.out.println("Derived says hi");
    }
}

public class Main {
    public static void main(String[] args) {
        Base b = new Derived();
        b.greet(); 
        b.say();   
    }
}

🖍️
Hello from Base
Derived says hi

Base b = new Derived();
b.greet();  // 정적 메서드 → 참조 변수 타입 기준 → Base.greet()
b.say();    // 인스턴스 메서드 → 실제 객체 기준 → Derived.say()
  • greet()은 static → 오버라이딩 아님 → Base 기준
  • say()는 오버라이딩 → Derived 기준
profile
ʚȉɞ

0개의 댓글