2024. 1. 21. 23:14ㆍ공부 중/Java
1. 상속
가. 객체지향 언어의 특징
특성 | 내용 |
추상화 | 현실의 객체를 추상화 해서 클래스를 구성한다. |
다형성 | 하나의 객체를 여러 가지 타입으로 참조할 수 있다. |
상속 | 부모 클래스의 자산을 물려받아 자식을 정의함으로 코드의 재사용이 가능하다. |
캡슐화 | 데이터를 외부에 직접 노출시키지 않고 메서드를 이용해 보호할 수 있다. |
나. 상속
- Inheritance
- 상위 클래스의 멤버를 하위 클래스에서 재사용하기 위함.
- 유지보수성 향상
extends
키워드 사용.- 부모의 생성자와
private
제한자가 붙은 경우는 상속되지 않음.
public class Person {
String name;
void eat() {
System.out.println("냠냠");
}
void jump() {
System.out.println("폴짝");
}
}
public class SpiderMan extends Person {
boolean isSpider;
void fireWeb() {
System.out.println("어떻게?");
}
}
public class SpiderTest {
public static void main(String[] args) {
SpiderMan sman = new SpiderMan();
sman.isSpider = true;
sman.fireWeb();
sman.jump();
}
}
다. Object 클래스
모든 클래스의 공통 조상.
별도의 클래스를 상속받지 않는다면 extends Object
를 생략됨.
모든 클래스에는 Object 클래스에 정의된 메서드가 있음.
- java.lang.Object
- registerNative(): void
- getClass(): java.lang.Class<?>
- clone(): java.lang.Object
- finalize() void
- (): void
- 대부분 클래스에서 재정의하는 것
- hashCode(): int
- equals(Obj: java.lang.Object): boolean
- toString(): java.lang.String
- 멀티 스레드에서 사용하는 것
- notify(): void
- notifyAll(): void
- wait(timeout: long): void
- wait(timeout: long, nanos int): void
- wait(): void
라. 다양한 상속 관계
가. 단일 상속
자바에서는 단일 상속만 지원.
대신 interface와 포함 관계로 한계를 극복한다.
나. 포함 관계
상속 이외에 클래스를 재활용하는 방법.
2개 이상의 클래스에서 특성을 가져올 때 하나는 상속, 나머지는 멤버 변수로 처리.
public class Spider {
void jump() {
System.out.println("깡총거미는 어마어마한 점프!!");
}
void fireWeb() {
System.out.println("슉슉~~");
}
}
Spider
라는 클래스를 생성한다.
public class SpiderMan extends Person {
boolean isSpider;
// has a 관계 (포함관계)
Spider spider;
public SpiderMan() {
this.spider = new Spider();
}
void fireWeb() {
if(isSpider) {
spider.fireWeb();
}else {
System.out.println("지금은 안됨");
}
}
}
SpiderMan
은 spider
를 가지고 있으므로 spider
를 활용할 수 있다.
2. 메서드 재정의
가. 오버라이딩
- Overriding
- 조상 클래스에 정의된 메서드를 자식 클래스에 적합하게 덮어쓰는 것.
- 조건
- 메서드 이름이 같아야 한다.
- 매개 변수의 개수, 타입, 순서가 같아야 한다.
- 리턴 타입은 같아야 한다.
- 접근 제한자는 부모 보다 범위가 넓거나 같아야 한다.
- 조상보다 더 큰 예외를 던질 수 없다.
public class SpiderMan extends Person {
boolean isSpider;
// has a 관계 (포함관계)
Spider spider;
public SpiderMan() {
this.spider = new Spider();
}
void fireWeb() {
if(isSpider) {
spider.fireWeb();
}else {
System.out.println("지금은 안됨");
}
}
void jump() {
if(isSpider) {
spider.jump();
} else {
System.out.println("두 다리로 힘껏 점프");
}
}
}
jump()
를 재정의했다.
1) 이런 경우는?
public class Person {
private int age;
private String name;
void m1() { }
}
public class SubPerson extends Person {
//@Override
void m1(int a) { }
}
결과는?
에러가 발생하지도 않고 오버라이딩도 아니다.
자식 클래스에서 추가된 메서드로 인식하기 때문이다.
@Override
를 사용해서 이런 실수를 방지할 수 있다.
@Override
를 활성화하면 해당 메서드는 반드시 부모의 메서드를 올바르게 재정의해야 한다.
그렇지 않으면 오류가 발생한다.
나. super
1) super.
public class SpiderMan extends Person {
boolean isSpider;
// has a 관계 (포함관계)
Spider spider;
public SpiderMan() {
this.spider = new Spider();
}
void fireWeb() {
if(isSpider) {
spider.fireWeb();
}else {
System.out.println("지금은 안됨");
}
}
void jump() {
if(isSpider) {
spider.jump();
} else {
super.jump() // 변경
}
}
}
super.jump()
: 조상 클래스(Person
)의 멤버에 접근하는 방법.
class Parent {
String x = "parent";
}
class Child extends Parent{
String x = "child";
void method(){
String x = "method";
System.out.println("x : " + x); // x : method
System.out.println("this.x : " + this.x); // this.x : child
System.out.println("super.x : " + super.x); // supder.x : parent
}
}
/*
x : method
this.x : child
supder.x : parent
*/
사용된 위치에서 범위를 확장해 가며 처음 만난 선언부에 연결됨.
(method 내부 → 해당 클래스 멤버 변수 → 조상 클래스 멤버 변수)
2) super()
- 조상 클래스의 생성자 호출
- 자식 클래스 생성자의 맨 첫 줄에서만 호출 가능
- 명시적으로
this()
또는super()
가 호출되지 않는 경우 컴파일러가super()
자동으로 삽입. - 결과적으로 가장 상위의
Object
까지 객체가 만들어진다. super()
와this()
는 같이 사용할 수 없다.
public Person(String name) {
super();
this.name = name;
}
상위 생성자를 수정하면 하위 클래스의 생성자도 영향을 받는다.
public SpiderMan(){
this("Peter Parker");
}
public SpiderMan(String name) {
super(name);
this.spider = new Spider();
}
다. Annotation
컴파일러, JVM, 프레임워크 등이 보는 주석.
소스코드에 메타 데이터를 삽입.
@Deprecated
: 컴파일러에게 해당 메서드가 권장되지 않음을 알려줌.@Override
: 컴파일러에게 해당 메서드가 override한 메서드임을 알려줌.@SuppressWarnings
: 컴파일러에게 사소한 warning의 경우 무시하라 알려줌.
@Override
void jumps() {
if(isSpider) {
spider.jump();
} else {
super.jump();
}
}
@Override
가 붙어있지 않았다면 새로운 메서드를 생성하는 것으로 컴파일러는 해석했을 것.
하지만 @Override
붙어있다면 컴파일러는 개발자가 실수한 것을 알아차리고 알려준다.
3. Package & import
가. Package
물리적으로 패키지는 클래스 파일을 담고 있는 디렉터리다.
많은 클래스를 의미 있는 경로로 계층적으로 관리.
모든 클래스는 반드시 하나의 패키지 안에 포함되어야 한다.
(생략 시 default package에 속하게 되지만 권장하지 않음.)
com.company.project.service
com.company
: 회사의 identityproject
: 프로젝트이름service
: 용도
나. import
다른 클래스를 사용하고 싶을 때.
import java.util.*;
사용해도 성능에 문제가 없음!
java.util.List list = new java.util.ArrayList();
동일한 이름을 사용하는 다른 클래스의 경우 import
한 package의 이름을 입력한다.
java.lang.*;
default import package로 개발자가 추가하지 않아도 컴파일러가 자동으로 추가한다.
다. static import
int ret = Math.max(a,b);
Math.max()
는 static method다.
import static java.lang.Math.max;
//또는 import static java.lang.Math.*;
int ret = max(a,b);
static import 방식으로 max()
로 줄여 사용할 수 있다.
import static java.lang.System.*;
...
//System.out.println(data);
out.println(data);
Sytem.out.println()
도 out.println()
으로 줄일 수 있다.
참고만 하자.
4. 제한자
가. 제한자
- modifier
- 접근 제한자 :
public
,protected
,package
,private
- 그 외 제한자 :
static
,final
,abstract
,synchronized
- 접근 제한자 :
- 순서는 무관하나 일반적으로 접근 제한자를 가장 앞에 배치한다.
나. final
더 이상 바뀔 수 없음.
1) 용도
final class
: 더 이상 상속할 수 없음final method
: 더 이상 재정의 할 수 없음final variable
: 더 이상 값을 바꿀 수 없음
2) Blank final
자바는 Blank final
을 지원한다.
값이 할당되지 않은 멤버 변수에 대하여 생성자에서 1회 초기화할 수 있다.
3) static final
static final
: 모든 곳에서 공유되는 유일한 상수.
다. 접근 제한자
Access modifier.
부모의 제한자 범위와 같거나 넓은 범위로만 사용 가능.
웬만하면 private
사용하기.
'공부 중 > Java' 카테고리의 다른 글
[Java] 인터페이스 (0) | 2024.01.22 |
---|---|
[Java] 다형성 (0) | 2024.01.22 |
[Java] 객체지향 (0) | 2024.01.21 |
[Java] 배열 (0) | 2024.01.21 |
[Java] 조건문, 반복문 (0) | 2024.01.21 |