2023. 1. 25. 09:19ㆍJAVA언어
상속
상속의 조건
- 자손은 조상의 모든 멤버를 상속 받습니다.
생성자 와 초기화 블럭은 제외됩니다.
- 자손의 멤버 개수는 조상보다 적을 수 없습니다.
항상 같거나 많습니다.
- 자손의 변경은 조상에게 영향을 미치지 않습니다.
포함 관계
관계 설정

오버라이딩
- 메서드 내부의 내용만 변경할 수 있습니다.
오버라이딩의 조건
- 선언부가 조상 클래스의 메서드와 일치해야 합니다.
- 접근 제어자를 조상 클래스의 메서드 보다 좁은 범위로 변경할 수 없습니다.
- 예외는 조상 클래스의 메서드 보다 많이 선언할 수 없습니다.
오버로딩 과 오버라이딩 비교하기
오버로딩 : 기존에 없는 새로운 메서드를 정의하는 것입니다.
오버라이딩 : 상속받은 메서드의 내용을 변경하는 것입니다.
super와 super()
super
객체 자신을 가리키는 참조변수입니다.
인스턴스 메서드(생성자) 내에서만 존재합니다.
조상의 멤버를 자신의 멤버와 구별할 때 사용합니다.
package와 import
package
서로 관련된 클래스의 묶음입니다.
패키지를 하나의 폴더라고 생각하시면 됩니다.
클래스의 실제 이름은 패키지를 포함합니다.
package 선언
패키지는 소스파일의 첫 번째 문장으로 단 한번만 선언합니다.
같은 소스 파일의 클래스들은 모두 같은 패키지에 속합니다.
패키지 선언이 없으면 default 패키지에 속하게 됩니다.
클래스 패스(classpath)
클래스 파일(.class)의 위치를 알려주는 경로입니다.
calsspath(환경변수)로 관리하며 경로간의 구분자는 ';'를 사용합니다.
classpath에 패키지의 루트를 등록해줘야합니다.
import
클래스를 사용할 때 패키지 이름을 생략할 수 있게 해줍니다.
컴파일러에게 클래스가 속한 패키지를 알려줍니다.
java.lang 패키지는 중요한 클래스들이 모여있는 패키지이기 때문에 import를 생략할 수 있게 되어있습니다.
선언방법 : import 패키지명.클래스명;
import는 패키지와 클래스 선언 사이에 존재한다.
static import
static 멤버를 사용할 때 클래스 이름을 생략할 수 있게 해줍니다.
- import static java.lang.System.out;
- 위처럼 선언 해주면 out.print("출력!"); 이렇게 사용할 수 있습니다.
접근제어자
제어자
클래스와 클래스의 멤버(변수, 메서드)에 부가적인 의미를 부여합니다.
- 접근 제어자 : public, protexted, (default), private
- 그 외 : static, final, abstract...
하나의 대상에 여러 제어자를 같이 사용 가능합니다.(접근 제어자는 하나만)
- 순서는 상관없지만 주로 접근 제어자를 제일 왼쪽에 선언합니다.
- public static void main(String[] args) {}
static
멤버변수, 메서드, 초기화 블럭에 static이 사용될 수 있습니다.
final
클래스, 메서드, 멤버변수, 지역변수에 final이 사용될 수 있습니다.
[참고] 대표적인 final 클래스로는 String과 Math가 있다.
생성자를 이용하여 final 멤버변수를 초기화 할 수 있습니다.
- final이 붙은 변수는 상수이기 때문에 보통은 선언과 동시에 초기화를 진행해야 하지만 인스턴스 변수의 경우 생성자에 의해서 초기화 할 수 없습니다.
abstract
클래스, 메서드에 abstract이 사용될 수 있습니다.
[참고] 추상메서드가 없는 클래스도 abstact를 붙여서 추상클래스로 선언하는 것이 가능하기는 하지만 그렇게
해야할 이유는 없다.
접근 제어자
private : 같은 클래스 내에서만 접근이 가능합니다.
(default) : 같은 패키지 내에서만 접근이 가능합니다. (생략가능)
protected : 같은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근이 가능합니다.
public : 접근 제한이 전혀 없습니다.
접근 제어자의 조합 주의!
- 메서드에 static과 abstract를 함께 사용할 수 없습니다.
- static 메서드는 몸통이 있는 메서드에서만 사용할 수 있기 때문입니다.
- 클래스에 abstract와 final을 동시에 사용할 수 없습니다.
- 클래스에 사용 되는 final은 클래스를 확장할 수 없다는 의미이고, abstract는 상속을 통해서 완성되어야 한다는
의미이므로 서로 모순되기 때문입니다.
- abstract 메서드의 접근 제어자가 private 일 수 없습니다.
- abstract 메서드는 자손 클래스에서 구현하기 위해 접근해야 하기 때문입니다.
- 메서드에 private와 final을 같이 사용할 필요는 없습니다.
- 접근 제어자가 private인 메서드는 오버라이딩될 수 없기 때문입니다.
- 이 둘 중 하나만 사용해도 의미가 충분합니다.
캡슐화
접근 제어자를 사용하는 이유
외부로부터 데이터를 보호하기 위해
내부적으로만 사용되는 것을 외부로 노출시키지 않고 감치기 위해
이렇게 데이터를 보호하는 것을 캡슐화라고 부릅니다.
다형성
여러가지 형태를 가질 수 있는 능력입니다.
조상 타입의 참조변수로 자손타입의 객체를 다루는 것
- 조상 타입의 참조변수로 자손 타입의 객체를 다룰 수는 있습니다.
- 하지만 조상 타입에는 없는, 자손 타입만 가지고 있는 기능 및 속성들은 사용할 수 없습니다.
참조변수의 형변환
사용할 수 있는 멤버의 개수를 조절하는 것입니다.
조상, 자손 관계의 참조변수는 서로 형변환이 가능합니다.
A(객체) instanceof B(클래스) 연산자
A 객체가 B 클래스로부터 상속을 받았는지 확인할 수 있습니다.
참조변수를 형변환 하기 전에 형변환 가능 여부를 확인하기 위해 사용됩니다.
형변환 전에 반드시 instanceof 로 확인해야 합니다.
매개변수 다형성
참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨 줄 수 있습니다.
추상 클래스
추상 클래스의 형태
일반 클래스와 똑같은데 추상 메서드가 추가된 미완성 클래스
인터페이스
추상 메서드의 집합
구현된 것이 전혀 없는 설계도
모든 멤버가 public 입니다.
상수 이외의 인스턴스 변수, 클래스 변수는 가질 수 없습니다.
interface 인터페이스이름{
public static final 타입 상수이름 = 값; // 상수
public abstract 메서드 이름(매개변수목록); // 추상 메서드
}
인터페이스의 상속
인터페이스의 조상은 인터페이스만 가능
인터페이스는 클래스처럼 Object가 최고 조상이 아닙니다.
추상 메서드는 어차피 상속 받으면서 구현부를 작성하기 때문에 충돌해도 상관 없습니다.
따라서 다중 상속이 가능합니다.
인터페이스 구현
인터페이스에 정의된 추상 메서드를 완성하는 것
class 클래스이름 implements 인터페이스이름 {...}
클래스에서 implements 라는 키워드를 사용하여 인터페이스를 구현
추상 클래스와 마찬가지로 구현을 다 못한 클래스는 미완성 클래스로 취급하기 때문에 abstract 제어자를 클래스에 추가해야 합니다.
인터페이스의 다형성
인터페이스 return 타입
인터페이스를 메서드의 반환 타입으로 지정할 수 있습니다.
인터페이스의 장점
두 객체 간의 '연결, 대화, 소통'을 돕는 '중간 다리 역할'을 합니다.
선언(설계)과 구현을 분리시킬 수 있게 해줍니다.
interface Repository {
public int[] getData(); // 데이터를 가져오는 추상 메서드
}
class DatabaseA implements Repository {
@Override
public int[] getData() {
System.out.println("Mysql 연결");
return new int[]{55, 44, 33, 22, 11, 77, 88};
}
}
class DatabaseB implements Repository {
@Override
public int[] getData() {
System.out.println("Oracle 연결");
return new int[]{1, 2, 3, 4, 5, 6, 7};
}
}
class DatabaseAdmin {
Repository repository = new DatabaseA();
// Repository repository = new DatabaseB();
public String getData() {
return Arrays.toString(repository.getData());
}
}
class User {
DatabaseAdmin databaseAdmin = new DatabaseAdmin();
}
class DatabaseMain {
public static void main(String[] args) {
User user = new User();
System.out.println(user.databaseAdmin.getData());
// user 사용자가 갑자기 데이터 반환 방식 교체를 요구했습니다
// 그런데 그 방식이 기존의 Database 로는 불가능 하다면?
// 그래서 DB 교체가 필요해 졌습니다.
// 이럴 경우 Repository repository = new DatabaseA();
// 를 Repository repository = new DatabaseB(); 로 교체하면 됩니다.
// User 자체는 전혀 수정되지 않기때문에 이런걸 느슨한 결합이라 부릅니다.
}
}
'JAVA언어' 카테고리의 다른 글
JAVA_#5_1 (0) | 2023.01.26 |
---|---|
복습 (1) | 2023.01.26 |
자습 (0) | 2023.01.24 |
헷갈리는 부분 복습#2 (0) | 2023.01.23 |
헷갈리는 부분 복습#1 (0) | 2023.01.22 |