1. 상속(Inheritance)
- 기존의 클래스로 새로운 클래스를 작성하는 것.(코드의 재사용)
- 두 클래스를 부모와 자식으로 관계를 맺어주는 것.
- 자손은 조상의 모든 멤버를 상속 받는다.(생성자, 초기화 블럭 제외)
- 자손의 멤버 개수는 조상보다 적을 수 없다.(같거나 많다)
- 자손의 변경은 조상에 영향을 끼치지 않는다.
클래스 간의 관계 결정
- 상속관계 : '~은 ~이다.(is -a)'
- 포함관계 : '~은 ~을 가지고 있다.(has -a)'
- 클래스의 멤버로 참조변수를 선언하는 것
- 작은 단위의 클래스를 만들고, 이들을 조합해서 클래스를 만든다.
단일 상속
- Java는 단일상속만 허용한다.(C++은 다중상속 허용)
- 비중이 높은 클래스 하나만 상속관계로, 나머지는 포함관계로 설정
Object 클래스
- 모든 클래스의 조상
- 부모가 없는 클래스는 자동적으로 Object클래스를 상속받게 된다.
오버라이딩(Overriding)
- 상속 받은 조상의 메서드를 자신에 맞게 변경하는 것
- 조건
- 선언부가 조상 클래스의 메서드와 일치해야 한다.
- 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
- 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
- 오버로딩 vs. 오버라이딩
- 오버로딩 : 기존에 없는 새로운 메서드를 정의하는 것(new), 상속과는 관계 없음
- 오버라이딩 : 상속 받은 메서드의 내용을 변경하는 것(change, modify)
생성자 super()
- 조상의 생성자를 호출할 때 사용
- 조상의 멤버는 조상의 생성자를 호출해서 초기화
- 생성자의 첫 줄에 반드시 생성자를 호출해야 한다.
- 그렇지 않으면 컴파일러가 생성자의 첫 줄에 super();를 삽입
- 만약 super()에 대한 생성자가 부모 클래스에 없다면 에러 발생
참조변수 super
- 객체 자신을 가리키는 참조변수. 인스턴스 메서드(생성자)내에만 존재
- 조상의 멤버를 자신의 멤버와 구별할 때 사용
2. 패키지(Package)
- 서로 관련된 클래스의 묶음
- 클래스는 클래스 파일. 패키지는 폴더. 하위 패키지는 하위 폴더
- 클래스의 실제 이름(full name)은 패키지를 포함
클래스 패스(classpath)
- 클래스 파일의 위치를 알려주는 경로(path)
- 환경변수 classpath로 관리하며, 경로간의 구분자는 ';'를 사용
- classpath(환경변수)에 패키지의 루트를 등록해줘야 함
import문
- 클래스를 사용할 때 패키지 이름을 생략할 수 있다.
- 컴파일러에게 클래스가 속한 패키지를 알려준다.
- java.lang 패키지의 클래스는 import 하지 않고도 사용할 수 있다.
- import문의 선언
- import 패키지명.클래스명;
- import 패키지명.*;
- 패키지문과 클래스 선언의 사이에 선언한다.
- import문은 컴파일 시에 처리되므로 프로그램의 성능에 영향 없음.
- 이름이 같은 클래스가 속한 두 패키지를 import할 때는 클래스 앞에 패키지명을 붙여줘야한다.
- 다음의 두 코드는 서로 의미가 다르다.
import java.util.*;
import java.text.*;
import java.*; // java 패키지의 모든 클래스를 의미. 패키지는 포함 안됨
static import문
- static 멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다.
- 쓰는 이유 : 코드 가독성. 하지만 왠만하면 쓰지 않고 꼭 필요할 때만 사용
3. 제어자(Modifier)
- 클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여
- 하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만)
- 접근 제어자를 제일 왼쪽에 쓰는 것이 보편적
- 접근 제어자 : public, protected, (default), private
- 그 외 : static, final, abstract, native, transient, synchronized, volatile, strictfp
- static : 클래스의, 공통적인
- 멤버변수
- 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다.
- 클래스 변수는 인스턴스를 생성하지 않고도 사용 가능하다.
- 클래스가 메모리에 로드될 때 생성된다.
- 메서드
- 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
- static메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다.
- final : 마지막의, 변경될 수 없는
- 클래스
- 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.
- final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
- 메서드
- 변경될 수 없는 메서드
- final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
- 멤버변수, 지역변수
- 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.
- abstract : 추상의, 미완성의
- 클래스
- 클래스 내에 추상 메서드가 선언되어 있음을 의미한다.
- 메서드
- 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다.
- 추상 클래스를 사용하려면 상속을 통해 클래스를 완성 시켜줘야 사용 가능(구상 클래스)
접근 제어자(access modifier)
- private : 같은 클래스 내에서만 접근이 가능하다.
- (default) : 같은 패키지 내에서만 접근이 가능하다.
- protected : 같은 패키지 내에서 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.
- public : 접근 제한이 전혀 없다.
- 클래스 : public, (default) 가능
- 멤버 : public, (default), private, protected 모두 가능
캡슐화와 접근 제어자
- 접근 제어자를 사용하는 이유
- 외부로부터 데이터를 보호하기 위해서
- 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서
3. 다형성(Polymorphism)
- 여러 가지 형태를 가질 수 있는 능력
- 조상 타입 참조 변수로 자손 타입 객체를 다루는 것
- 객체와 참조변수의 타입이 일치할 때와 일치하지 않을 때의 차이
SmartTv s = new SmartTv(); // 모든 기능 사용 가능
Tv t = new SmartTv(); // 일부 기능 사용 불가능
- 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다.
Tv t = new SmartTv(); // 가능
SmartTv s = new Tv(); // 에러
참조변수의 형변환
- 사용할 수 있는 멤버의 갯수를 조절하는 것
- 조상 자송 관계의 참조변수는 서로 형변환 가능
instanceof 연산자
- 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환
- 형변환 전에 반드시 instanceof로 확인해야 함
- 참조변수의 형변환은 왜 하나요?
- 참조변수를 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해서
매개변수의 다형성
- 참조형 매개변수는 메서드 호출 시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
class Product {}
class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}
// 오버로딩 활용하여 작성
void buy(Tv t) {}
void buy(Computer c) {}
void buy(Audio a) {}
// 다형성 활용하여 작성 - 매개변수에 tv, computer, audio 다 들어올 수 있음
void buy(Product p) {}
여러 종류의 객체를 배열로 다루기
- 조상타입의 배열에 자손들의 객체를 담을 수 있다.
Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
4. 추상 클래스(Abstract class)
추상 클래스
- 미완성 설계도. 미완성 메서드를 갖고 있는 클래스
abstract class Player {
abstract void play(int pos);
}
- 다른 클래스 작성에 도움을 주기 위한 것. 인스턴스 생성 불가.
- 상속을 통해 추상 메서드를 완성해야 인스턴스 생성 가능
추상 메서드
- 미완성 메서드. 구현부(몸통)가 없는 메서드
- 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우
추상 클래스의 작성
- 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존 클래스의 공통 부분을 뽑아서 추상 클래스를 만든다.
- 추상화 ↔ 구체화
- 추상화된 코드는 구체화된 코드보다 유연하다 = 변경에 유리
5. 인터페이스(Interface)
- 추상 메서드의 집합
- 구현된 것이 전혀 없는 설계도.(모든 멤버가 public)
인터페이스의 상속
- 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상이 아님)
- 다중 상속이 가능(추상 메서드는 충돌해도 문제 없음)
인터페이스의 구현
인터페이스를 이용한 다형성
인터페이스의 장점
- 두 대상(객체) 간의 연결, 대화, 소통을 돕는 중간 역할을 한다.
- 선언(설계)와 구현을 분리시킬 수 있게 한다.
- B가 변경되어도 A는 안바꿀 수 있게 된다.(느슨한 결합)
- A → B 일때, B가 C로 바뀌면 A도 바꿔줘야 함.
- A → I(인터페이스) → B 일때, B가 바껴도 A를 안 바꿔도 됨.
- 직접적인 관계의 두 클래스(A-B)
- 개발 시간을 단축할 수 있다.
- 변경에 유리한 유연한 설계가 가능하다.
- 표준화가 가능하다.
- 서로 관계없는 클래스들을 관계를 맺어줄 수 있다.
- marine, scv, tank → GroundUnit
디폴트 메서드와 static 메서드
- 인터페이스에 디폴트 메서드, static 메서드 추가 가능(JDK 1.8 부터)
- 인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어려움(모든 구현체에 구현해줘야 하기 때문에
6. 내부 클래스(Inner class)
- 클래스 안의 클래스
class A {
class B { }
}
내부 클래스의 장점
- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
- 코드의 복잡성을 줄일 수 있다.(캡슐화)
내부 클래스의 종류와 특징
- 내부 클래스의 종류와 유효범위는 변수와 동일
- 인스턴스 내부 클래스 : 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 인스턴스멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용 될 목적으로 선언된다.
- 스태틱 내부 클래스 : 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static 멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static 메서드에서 사용 될 목적으로 선언된다.
- 지역 내부 클래스 : 외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다.
- 익명 클래스(anonymous class) : 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용)
- 내부 클래스의 제어자와 접근성
- 내부 클래스의 제어자는 변수에 사용 가능한 제어자와 동일
- 외부 클래스에선 (default), public만 가능하지만, 내부 클래스는 private, protected도 가능