Java 개념 정리 2

고 연우·2022년 8월 26일
0

Java

목록 보기
2/6

상속( inheritance )

  • 기존의 클래스에 기능을 추가하거나 재정의하여 새로운 클래스를 정의하는 것
  • 부모 클래스( parent class ), 상위 클래스( super class ), 기초 클래스( base class ) : 기존에 정의되어 있던 클래스
  • 자식 클래스( child class ), 하위 클래스( sub class ), 파생 클래스( derived class ) : 상속을 통해 새롭게 작성되는 클래스
    • 부모 클래스의 필드와 메소드만 상속됨.

Ex)

class Parent {
    private int a = 10;
    public int b = 20;
}

class Child extends Parent {
    public int c = 30;

    void display() {
        // System.out.println(a);       // 상속받은 private 필드는 참조 불가능
        System.out.println(b);
        System.out.println(c);
    }
}

public class Java100_variable_HelloJava {
    public static void main(String[] args) {
        Child ch = new Child();
        ch.display();
    }

super 키워드

  • 부모 클래스로부터 상속받은 필드나 메소드를 자식 클래스에서 참조하는데 사용하는 참조 변수

Ex)

class Parent {
    int a = 10;
}

class Child extends Parent {
    int a = 20;

    void display() {
        System.out.println(a);
        System.out.println(this.a);
        System.out.println(super.a);
    }
}

public class Java100_variable_HelloJava {
    public static void main(String[] args) {
        Child ch = new Child();
        ch.display();
    }
}

//결과
20
20
10

super() 메소드

  • super() 메소드는 부모 클래스의 생성자를 호출할 때 사용
  • 자바에서는 자동으로 super() 메소드를 추가하여, 부모 클래스의 멤버를 초기화할 수 있게 해줌
    • 하지만 부모 클래스에 매개변수를 가지는 생성자를 하나라도 선언 시, super() 메소드는 자동으로 추가되지 않음
  • 따라서 부모 클래스에서 매개변수를 가진 생성자 선언 시 기본 생성자도 명시적으로 선언해줘야 함

Ex)

class Parent {
    int a;

    Parent() {
        a = 10;
    }

    Parent(int n) {
        a = n;
    }
}

class Child extends Parent {
    int b;

    Child() {
        // super(40);
        b = 20;
    }

    void display() {
        System.out.println(a);
        System.out.println(b);
    }
}

public class Java100_variable_HelloJava {
    public static void main(String[] args) {
        Child ch = new Child();
        ch.display();
    }
}

//결과
10
20

//주석 해제 시
40
20

메소드 오버라이딩( method overriding )

  • 상속 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 시그니쳐를 갖는 메소드로 다시 정의하는 것
  • 상속받은 부모 클래스의 메소드를 재정의하여 사용하는 것
  • 조건
    • 메소드의 선언부는 기존 메소드와 완전히 같아야 함
    • 메소드의 반환 타입은 부모 클래스의 반환 타입으로 타입 변환할 수 있는 타입이라면 변경 가능
    • 부모 클래스의 메소드보다 접근 제어자를 더 좁은 범위로 변경할 수 없음
    • 부모 클래스의 메소드보다 더 큰 범위의 예외 선언 불가능

Ex)

class Parent {
    void display() {
        System.out.println("부모 클래스의 display() 메소드입니다.");
    }
}

class Child extends Parent {
    void display() {
        System.out.println("자식 클래스의 display() 메소드입니다.");
    }
}

public class Java100_variable_HelloJava {
    public static void main(String[] args) {
        Parent pa = new Parent();
        pa.display();

        Child ch = new Child();
        ch.display();

        Parent pc = new Child();
        pc.display();
    }
}

다형성( polymorphism )

  • 하나의 객체가 여러 가지 타입을 가질 수 있는 것
    Ex)
class Parent{ ... }
class Child extends Parent{ ... }

1. Parent pa = new Parent();    // 허용
2. Child ch = new Child();      // 허용
3. Parent pc = new Child();     // 허용
4. Child cp = new Parent();     // 오류 발생
  • 코드 설명
    • 1, 2. 특정 타입의 참조 변수로는 같은 타입의 인스턴스 참조 가능
      • 참조 변수가 사용할 수 있는 멤버의 개수가 실제 인스턴스의 멤버 개수와 같음
      1. 부모 클래스 타입의 참조 변수로는 자식 클래스 타입의 인스턴스를 참조 가능
      • 참조 변수가 사용할 수 있는 멤버의 개수가 실제 인스턴의 멤버 개수보다 적음
      1. 자식 클래스 타입의 참조 변수로는 부모 클래스 타입의 인스턴스 참조 불가능
      • 참조 변수가 사용할 수 있는 멤버의 개수가 실제 인스턴스의 멤버 개수보다 많기 때문
      • 클래스는 상속을 통해 확장 가능, 축소 불가능 이므로 자식 클래스에서 사용할 수 있는 멤버의 개수는 부모 클래스와 같거나 많게 됨
  • 참조 변수의 타입 변환
    • 서로 상속 관계에 있는 클래스 사이에만 타입 변환 가능
    • 자식 클래스 타입에서 부모 클래스 타입으로의 타입 변환 생략 가능
    • 부모 클래스 타입에서 자식 클래스 타입으로의 타입 변환은 반드시 명시
    • 형식 : (변환할 타입의 클래스 이름) 변환할 참조 변수

Ex)

class Parent{ ... }
class Child extends Parent{ ... }
class Brother extends Parent{ ... }

Parent pa01 = null;
Child ch = new Child();
Parent pa02 = new Parent();
Brother br = null;

pa01 = ch;    // pa01 = (Parent)ch; 와 같으며, 타입 변환 생략 가능
br = (Brother)pa02;    // 타입 변환 생략 불가능
br = (Brother)ch;      // 직접적인 상속 관계가 아니므로 오류 발생
  • instanceof 연산자 : 참조 변수가 참조하고 있는 인스턴스의 실제 타입 확인할 수 있도록 해줌
    • 참조변수 instanceof 클래스 이름
    • 왼쪽에 전달된 참조 변수가 실제로 참조하고 있는 인스턴스의 타입이 오른쪽에 전달된 클래스 타입이면 true 반환, 아니거나 참조 변수가 null일 경우 false 반환
      Ex)
class Parent { }
class Child extends Parent { }
class Brother extends Parent { }

public class Java100_variable_HelloJava {
    public static void main(String[] args) {
        Parent p = new Parent();
        System.out.println(p instanceof Object); // true
        System.out.println(p instanceof Parent); // true
        System.out.println(p instanceof Child); // false
        System.out.println();

        Parent c = new Child();
        System.out.println(c instanceof Object); // true
        System.out.println(c instanceof Parent); // true
        System.out.println(c instanceof Child); // true
    }
}

// 결과
true
true
false

true
true
true

추상 클래스( abstract class)

추상 메소드( abstract method ) : 자식 클래스에서 반드시 오버라이딩해야만 사용할 수 있는 메소드
  • 추상 메소드가 포함된 클래스를 상속받는 자식 클래스가 반드시 추상 메소드를 구현하도록 하기 위함
  • 중복 또는 공통적인 부분은 미리 다 만들어진 것을 사용하고, 이를 받아 사용하는 쪽에서는 자신에게 필요한 부분만을 재정의하여 사용함으로써 생상성이 향상되고 배포 등이 쉬워지기 때문
  • 추상 메소드는 선언부만 존재하며 구현부는 작성되지 않음
  • 구현부는 자식 클래스에서 오버라이딩하여 사용하는 것
추상 클래스( abstract class ) : 하나 이상의 추상 메소드를 포함하는 클래스
  • 인스턴스 생성 불가능 : 동작이 정의되어 있지 않은 추상 메소드를 포함하고 있음
  • 상속을 통해 자식 클래스 생성 -> 자식 클래스에서 추상 클래스의 모든 추상 메소드를 오버라이딩 -> 자식 클래스의 인스턴스 생성 가능
  • 생성자, 필드, 일반 메소드 포함 가능

Ex)

abstract class Animal {
    abstract void cry();
}
// 이런 형식으로 추상 클래스, 추상 메소드 생성

class Cat extends Animal {
    void cry() {
        System.out.println("냐옹냐옹!");
    }
}

class Dog extends Animal {
    void cry() {
        System.out.println("멍멍!");
    }
}

public class Java100_variable_HelloJava {
    public static void main(String[] args) {
        // Animal a = new Animal() // 추상 클래스는 인스턴스 생성 불가능
        Cat c = new Cat();
        Dog d = new Dog();

        c.cry();
        d.cry();
    }
}

인터페이스( interface )

  • 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스 의미
  • 다중 상속 지원
  • 추상 메소드와 상수만 포함 가능
  • 선언
접근제어자 interface 인터페이스이름 {
  publlic static final 타입 상수이름 =;
  public abstract 메소드이름(매개변수목록);
}
  • 모든 필드는 public static final, 모든 메소드는 public abstract 로 선언
    • 모든 인터페이스에 공통으로 적용되는 부분이므로 생략 가능
    • 컴파일 시 자바 컴파일러가 자동으로 추가 해줌
  • 인터페이스는 직접 인스턴스 생성 불가능
    • 인터페이스가 포함하고 있는 추상 메소드를 구현해 줄 클래스는 작성해야 함
    • class 클래스이름 implements 인터페이스 이름{ ... }
  • 인터페이스 상속과 구현 동시에 생성 가능
    • class 클래스이름 extend 상위클래스이름 implements 인터페이스이름{ ... }
  • 인터페이스 구현 Ex)
interface Animal {
    public abstract void cry();
}

class Cat implements Animal {
    public void cry() {
        System.out.println("냐옹냐옹");
    }
}

class Dog implements Animal {
    public void cry() {
        System.out.println("멍멍!");
    }
}

public class Java100_variable_HelloJava {
    public static void main(String[] args) {
        Cat c = new Cat();
        Dog d = new Dog();

        c.cry();
        d.cry();
    }
}
  • 다중 상속 Ex)
interface Animal {
    public abstract void cry();
}

interface Pet {
    public abstract void play();
}

class Cat implements Animal, Pet {
    public void cry() {
        System.out.println("냐옹냐옹");
    }

    public void play() {
        System.out.println("쥐 잡기 놀이하자");
    }
}

class Dog implements Animal, Pet {
    public void cry() {
        System.out.println("멍멍!");
    }

    public void play() {
        System.out.println("산책가자");
    }
}

public class Java100_variable_HelloJava {
    public static void main(String[] args) {
        Cat c = new Cat();
        Dog d = new Dog();

        c.cry();
        c.play();
        d.cry();
        d.play();
    }
}
  • 인터페이스 장점
    • 대규모 프로젝트 개발 시 일관되고 정형화된 개발을 위한 표준화 가능
    • 클래스의 작성과 인터페이스의 구현 동시에 진행 가능하며 개발 시간 단축 가능
    • 클래스와 클래스 간의 관계를 인터페이스로 연결하면, 클래스마다 독립적인 프로그래밍 가능

내부 클래스( inner class )

  • 하나의 클래스 내부에 선언된 또 다른 클래스

Ex)

class Outer {                           // 외부 클래스
  class InstanceInnerClass {}           // 인스턴스 클래스
  static class StaticInnerClass {}      // 정적 클래스
  void myMethod () {
    class LocalInnerClass {}            // 지역 클래스
  }
}
  • 익명 클래스( anonymous class ) : 클래스의 선언과 동시에 객체를 생성하므로, 단 하나의 객체만을 생성하는 일회용 클래스
    • 생성자 선언 불가능, 단 하나의 클래스나 단 하나의 인터페이스를 상속받거나 구현 가능
    • 매우 제한적인 용도에 사용, 구현해야 하는 메소드가 매우 적은 클래스 구현할 때 사용
// 익명 클래스는 선언과 동시에 생성하여 참조변수에 대입함
클래스이름 참조변수이름 = enw 클래스이름() {
  // 메소드의 선언
}

예외 처리( Exception handling )

  • 예외를 처리하기 위해 try / catch / finally 문 사용
    Ex)
try {
  // 예외를 처리하길 원하는 실행 코드;
} catch( e1 ) {
    // e1 예외가 발생할 경우에 실행될 코드;
} catch( e2 ) {
    // e2 예외가 발생할 경우에 실행될 코드;
}
finally {
  // 예외 발생 여부와 상관없이 무조건 실행될 코드;
}
  • 범위가 더 좁은 예외를 처리하는 catch 블록을 먼저 명시, 범위가 더 넓은 예외를 처리하는 catch 블록은 나중에 명시
    • Throwable 클래스 : 모든 예외의 조상이 되는 Exception 클래스와 모든 오류의 조상이 되는 Error 클래스의 부모 클래스
    • String getMessage() : 해당 throwable 객체에 대한 자세한 내용을 문자열로 반환함
    • void printStackTrace() : 해당 throwable 객체와 표준 오류 스트림( standard error stream )에서 해당 객체의 스택 트레이스를 출력함
    • String toString() : 해당 throwalbe 객체에 대한 간략한 내용을 문자열로 반환함
  • 예외처리 관련된 클래스는 추후에 알아보도록...

참고

TCP School - Java 강의 참고

0개의 댓글