2025.03.05 ~ 03.06
상속, 다형성, 자주 쓰는 API
상속(Inheritance)
상속
부모 클래스가 가지는 멤버(필드, 메소드)를 자식 클래스가 물려 받아 자신의 멤버인 것처럼 사용할 수 있도록 만든 기술
- 생성자는 물려 받지 않음
- 멤버 외에도 부모 클래스의 타입 또한 상속이 된다.(다형성의 토대)
- 자바는 단일상속(자식 클래스는 하나의 부모 클래스만 가지는)만 지원
접근제한자 class 자식클래스명 extends 부모클래스명{
}
public class Academy extends Company{
}
상속을 사용하는 이유
- 기존에 작성된 클래스의 멤버를 재사용할 수 있다.
수정사항이 생길 시 부모 클래스만 수정해도 전체적으로 적용된다. (유지보수성 증가)
- 클래스 간 계층 관계를 형성하여 다형성 문법의 토대가 된다.
상속 단점
- (상속 구조가 복잡할 시) 부모클래스의 기능을 추가/변경할 시 자식클래스가 정상적으로 동작하는지에 대한 예측이 힘들다.
- 자식클래스에서 중요하게 사용하는 기능인 경우 부모클래스를 변경할 시 자식 클래스에 모두 영향을 줄 수 있다.
- 부모클래스에서는 의미있었던 기능이 자식클래스에서는 무의미할 수 있다.
IS-A
자식 클래스는 (하나의)부모 클래스(단일상속)
super super()
인스턴스 생성 시 부모 클래스의 인스턴스도 함께 생성된다. 이 때 생성한 부모 인스턴스의 주소를 보관하는 레퍼런스 변수
-> 자식 클래스 내의 모든 생성자와 메소드 내에 묵시적으로 사용할 수 있는 레퍼런스 변수
super()는 부모 생성자를 호출하는 구문, 인자와 매개변수의 타입, 갯수, 순서가 일치하는 부모의 생성자를 호출
부모 클래스가 가지는 private 생성자를 제외한 나머지 생성자를 호출할 수 있도록 한 구문
만약 부모 클래스의 기본 생성자가 있고 그 안에 값이 있으면 자동으로 먼저 실행된다.->모든 클래스는 Object 클래스의 후손이기 때문에 java.lang.Object 클래스의 생성자를 호출
오버라이딩(Overriding)
부모클래스에서 상속받은 메소드를 자식 클래스가 재정의하여 사용하기 위한 기술
@override
부모랑같은 접근제한자 키워드 메소드(){
실행할 구문;
}
오버라이딩 성립 조건
- 메소드명 동일
- 메소드 리턴타입 동일
- 매개변수의 타입, 개수, 순서가 동일
- 부모 클래스의 private 메소드는 오버라이딩 불가능
- 부모 클래스의 final 키워드가 사용된 메소드는 오버라이딩 불가능
- 접근제어자는 부모 메소드와 같거나 더 넓은 범위여야 함
- 예외처리는 같은 예외이거나 더 구체적(하위)인 예외를 처리해야 함

다형성(Polymorphism)
다형성
하나의 인스턴스가 여러 가지 타입을 가질 수 있는 것
- 하나의 타입으로 여러 타입의 인스턴스를 처리
- 하나의 메소드 호출로 객체별로 각기 다른 방법으로 동작
객체지향 프로그래밍의 4대 특징(캡슐화, 상속, 다형성 + 추상화)
장점
- 여러 타입의 객체를 하나의 타입으로 관리할 수 있기 때문에 유지보수성과 생산성이 증가
- 상속관계에 있는 모든 객체는 동일한 메세지를 수신받을 수 있다
- 이런 동일한 메세지를 수신받아 처리하는 내용을
객체별로 다르게 할 수 있다
- 확장성이 좋은 코드를 작성할 수 있다.
- 결합도를 낮춰서 유지보수성을 증가시킬 수 있다.
동적 바인딩
컴파일 당시에는 해당 타입의 메소드와 연결되어 있다가 런타임 시 실제 해당 인스턴스가 메소드(오버라이딩 한 메소드)로 바인딩이 바뀌어 동작하는 것을 의미한다.
- 동적 바인딩의 성립 조건 : 상속 관계를 가지는 부모 자식 클래스에 오버라이딩 된 메소드를 호출해야 한다
업캐스팅 다운캐스팅
상속관계에 있지만 오버라이딩 한 것이 아닌 후손 객체가 고유하게 가지는 확장된 기능을 사용하기 위해서는 실제 인스턴스의 타입으로 다운캐스팅(클래스 형변환)을 해 주어야 한다.
- 상위 타입 형변환(up-casting) -> 묵시적으로 일어남
- 하위 타입 형변환(down-casting) -> 명시적으로 작성
부모클래스명(사용자 지정 참조 자료형) 참조변수 = new 자식클래스; // 업캐스팅
((자식클래스) 참조변수).자식메서드();
자식클래스명 참조변수 = (자식클래스) 부모클래스의참조변수; // 다운캐스팅
Instanceof 연산자
런티임 시 안전한 형변환을 하기 위해 사용하는 연산자
- 레퍼런스 변수가 실제로 어떤 클래스 타입의 인스턴스인지 확인하여 true or false를 반환
If(레퍼런스변수 instanceof 클래스타입){
// true일 때, 처리할 내용, 해당 클래스 타입으로 down-casting 함
}
추상클래스(Abstract Class)
추상 메소드(메소드의 기능이 없고 메소드의 헤더부만 존재하는 불완전한 메소드)를 0개 이상 포함하는 클래스
메소드의 선언부만 있고 구현부가 없는 메소드
- 추상클래스는 필드, 생성자(직접적으로 인스턴스 생성은 불가능), 일반적인 메소드, 추상메소드는 가질 수 있다.
- 상속 받은 하위 클래스는 추상클래스가 가지는 추상 메소드를 반드시 오버라이딩 해야 한다. (강제성 부여)
- 추상 메소드를 하나라도 포함하면 불완전 -> 추상 클래스
- 스스로 자신의 생성자를 활용한 인스턴스 생성이 불가능
- 추상클래스를 사용하려면 추상클래스를 상속받은 하위 클래스를 이용해서 인스턴스를 생성
class abstract AbstractClass(){
public abstract void method(); // 추상 메소드
public void method2(){ // 일반 메소드
}
}
추상 클래스를 사용하는 이유
- 다형성 적용을 위한 부모 타입 역할
- 추상 메소드를 통해 자식 클래스에 오버라이딩에 대한 강제성을 부여(추상 클래스를 상속받는 자식 클래스는 반드시 추상 메소드를 오버라이딩 해야 한다.)
- 필수 기능을 정의해 일관된 인터페이스(동일 기능)를 제공함에 있어 도움
인터페이스(Interface)
추상 메소드와 상수 필드만 가질 수 있는 클래스의 변형체
- 상속과 달리 implements라는 키워드를 사용하며 자식 클래스 입장에서 ‘상속 받았다’고 말하지 않고 ‘구현한다’라는 표현을 쓴다.
- 필드(변수)는 public static final만 가능하며 생략해도 자동으로 작성됨(상수만 된다)
- 메소드는 public abstract여야 하며 생략해도 자동으로 작성됨
interface TestInter{
public static final PI1 = 3.1415;
PI2 = 3.14;
public abstract void method1();
void method2();
}
인터페이스 구현
class Person implements Instinct, Serializable {
@ Override
public void eating(String food){
System.out.printIn("사람은 " + food + "를 요리하고 식기를 활용해 음식을 먹는다.");
}
}
인터페이스의 추상메소드 오버라이딩한 메소드로 동적바인딩에 의해 호출됨
오버라이딩 하지 않으면 인터페이스의 default 메소드로 호출됨
static 메소드는 인터페이스명.메소드명(); 으로 호출함
상수 필드 접근도 인터페이스명.필드명 으로 접근함
extends로 다른 클래스를 상속받는 경우에도 그것과 별개로 인터페이스도 추가 상속이 가능
단, extends 키워드를 앞에 작성하고 implements를 뒤에 작성한다. (순서 바뀌면 에러 발생)
접근제한자 class 클래스명 extends 다른클래스명 implements 인터페이스명1, 인터페이스명2{
}
- 인터페이스 안에 작성한 메소드는 묵시적으로 public abstract의 의미를 가진다. (다른 접근제한자 사용 불가)
-> 인터페이스의 메소드를 오버라이딩 하는 경우 반드시 접근제한자를 public으로 해야 오버라이딩이 가능
- 하지만, static 메소드는 작성이 가능
- 또한 default 키워드를 사용하면 (추상메소드 뿐만아니라) non-static 메소드도 작성 가능
public default void 메소드명(){
실행할 구문;
}
- static 메소드는 오버라이딩 안됨
- default메소드는 인터페이스에서만 작성가능 -> 키워드제외하면 오버라이딩 가능
인터페이스를 사용하는 이유
- 공유를 목적으로 하는 상수(public static final 필드)를 기반으로 모든 기능을 공통화(public abstract 메소드)해서 강제성을 부여할 목적으로 만들어 졌다.(공통된 인터페이스)
- 모든 클래스는 하나의 부모 클래스 외에도 여러 개의 인터페이스를 구현할 수 있다.(단일 상속 극복)

추상 클래스와 인터페이스의 차이점


추상 클래스와 인터페이스의 공통점

자주 쓰는 API
Object
자바에서 Object 는 최상위 부모 클래스
Object 클래스에는 다양한 메소드로 구성
- 모든 클래스는 Object 클래스를 상속하고 있으므로 Object 안에 있는 메소드를 사용할 수 있다.
- Object 클래스가 가지는 메소드를 오버라이딩 해서 사용하는 것도 가능
Object 주요 메소드
toString()
인스턴스의 정보를 문자열로 반환
- toString 메서드를 사용할 때 해시코드가 아닌 인스턴스 안에 값을 확인하고 싶다면 오버라이딩(재정의)
equals()
동일한 인스턴스인지 비교하는 기능
동등 객체 비교
- 매개변수로 전달받은 인스턴스와 값이 같은지 연산 -> true,false 반환
- 동일 객체 : 주소가 동일한 인스턴스(==연산)
- 동등 객체 : 주소는 다르더라도 필드값이 동일한 객체(equals)
hashCode()
객체를 식별하는 값
객체의 메모리 주소값을 이용해 해시코드를 만들어 반환
- 일반 규약 -> equals() 메소드를 재정의 하는 경우 반드시 hashCode() 메소드도 재정의
String
문자열을 나타내는 자료형 클래스
- String은 불변하기 때문에 값을 변경할 수가 없다. -> (StringBuffer, StringBuilder로 해결)
자주 사용하는 메소드
- charAt() : 해당 문자열의 특정 인덱스에 해당하는 문자를 반환
- compareTo(), compareToIgnoreCase() : 인자로 전달된 문자열과 사전 순으로 비교를 하여 두 문자열이 같다면 0을 반환, 인자로 전달된 문자열보다 작으면 음수를(왼<오), 크면 양수를(왼>오) 반환한다.
- 대소문자를 구분하여 비교함
- concat() : 문자열에 인자로 전달된 문자열을 합치기해서 새로운 문자열을 반환(왼+오)
- 원본 문자열에 영향 없음
- indexOf() : 문자열에서 특정 문자를 탐색하여 처음 일치하는 인덱스 위치를 정수형으로 반환(일치하는 문자가 없는 경우 -1)
- lastIndexOf() : 문자열 탐색을 뒤에서부터 하고 처음 일치하는 위치의 인덱스를 반환(일치하는 문자가 없는 경우 -1)
- trim() : 문자열의 앞 뒤에 공백을 제거한 문자열을 반환
- 원본 문자열에 영향 없음
- toLowerCase() : 모든 문자를 소문자로 변환
- 원본 문자열에 영향 없음
- toUpperCase() : 모든 문자를 대문자로 변환
- 원본 문자열에 영향 없음
- subString(시작인덱스, 끝인덱스) : 문자열의 일부분을 잘라내어 새로운 문자열을 반환
- 원본 문자열에 영향 없음
- replace(대체될문자열, 넣을문자열) : 문자열에서 대체할 문자열로 기존 문자열을 변경해서 반환
- 원본 문자열에 영향 없음
- length() : 문자열의 길이를 정수형으로 반환
- isEmpty() : 문자열의 길이가 0이면 true를 반환, 아니면 false를 반환
- 길이가 0인 문자열은 null과는 다르다.
문자열 객체를 만드는 방법
- "" 리터럴 형태 : 동일한 값을 가지는 인스턴스를 단일 인스턴스로 관리한다. (singleton)
- new Stirng("문자열") : 매번 새로운 인스턴스를 생성한다.
-> 동일한 문자열은 같은 주소를 갖는다.
문자열 분리
- split("구분자"|"구분자2") : 정규표현식을 이용하여 문자열을 분리, 공백 문자열 값 포함하여 비정형화된 문자열을 분리할 때 좋지만 속도가 느리다.
- split은 공백을 포함하기 때문에 마지막 공백은 출력이 되지 않는다.
- 마지막 구분자 사이에 값이 존재하지 않는 경우 이후 값도 추출하고 싶을 때
.split("/", -1);
- StringTokenizer(분리할 문자열,"구분자") : 문자열의 모든 문자들을 구분자로 하여 문자열을 분리, 공백 문자열을 무시하기 때문에 정형화된 문자열 패턴을 분리할 때 사용하기 좋다.
- 구분자를 생략하는 경우 공백이 기본 구분자이다.
- nextToken()으로 토큰을 꺼내면 해당 StringTokenizer의 토큰을 재사용 하는 것이 불가능(현재 남아 있는 토큰 중 가장 앞에 있는 토큰을 꺼내 반환)
이스케이프(escape) 문자
문자열 내에서 사용하는 문자 중 특수문자를 표현하거나 특수기능을 사용할 때 사용하는 문자
- \n : 개행(줄바꿈)
- \t : 탭
- \' : 작은 따옴표
- \" : 큰따옴표
- \ : 역슬래쉬 표시
split 시 이스케이프 문자를 사용해야 하는 특수문자도 존재
- 이스케이프 문자 사용 안하는 특수문자 : ~ ` ! @ # % & - _ = ; : ' \ " , < > /
- 이스케이프 문자를 사용하는 특수문자(\) : $ ^ * ( ) + | { } [ ] . ?
StringBuilder & StringBuffer
문자열 처리를 할 때 가장 많이 사용하게 되는 클래스
-
StringBuilder : Thread safe 하지 않음(스레드 동기화 기능 제공하지 않음)
-
StringBuffer : Thread safe, synchronized 키워드가 선언->멀티스레드에서 안전, 속도는 느림
-
.capacity() : 용량(현재 버퍼의 크기)을 정수형으로 반환하는 메소드 (문자열 길이 + 16이 기본 용량)
-
delete(삭제시작할 인덱스,삭제될 인덱스 바로 직후) : 시작 인덱스와 종료 인덱스를 이용해서 문자열에서 원하는 부문의 문자열을 제거
- 원본 영향을 미침
-
deleteCharAt(삭제할 인덱스) : 문자열 인덱스를 이용해서 문자 하나를 제거
- 원본 영향을 미침
-
insert(추가할 인덱스 위치,"추가할문자열") : 인자로 전달된 값을 문자열로 변환 후 지정한 인덱스 위치에 추가
- 원본에 영향을 미침
-
reverse() : 문자열 인덱스 순번을 역순으로 재배열
- 원본에 영향을 미침
Wrapper
래퍼클래스 : 기본 타입의 데이터 -> 인스턴스화
주방에서 사용하는 랩(Wrap)과 같은 의미로 감싼다는 의미

박싱(Boxing), 언박싱(UnBoxing)
오토 박싱(AutoBoxing), 오토 언박싱(AutoUnBoxing)
자동화된 박싱과 언박싱을 오토박싱, 오토 언박싱이라고 부름
JDK1.5부터 자바 컴파일러가 자동으로 처리
문자열 파싱(parsing)
문자열(String) 값을 기본자료형 값으로 변경
기본자료형 레퍼런스변수명 = 래퍼클래스명.parse레퍼런스면수명("문자열");
Character는 parsing 기능을 제공하지 않는다.
char 레퍼런스변수명 = "문자열".charAt(인덱스);
기본자료형 값을 문자열로 변경
-
toString() : 필드값을 문자열로 반환하는 메소드
String 참조변수명 = 래퍼변수명.valueOf(값).toString();
-
String클래스의 valueOf를 사용할 수도 있다.
String 참조변수명 = String.valueOf(값);
-
문자열 합치기를 이용해 String으로 변환할 수도 있다.
String 참조변수명 = 123 + "";
Time 패키지
불변한다는 장점 -> 멀티스레드 환경에서도 안전
time 패키지의 하위 패키지 : java.time.zone(시간대에 관련된 기능 제공)
Date 클래스
java.util에 속한 날짜 클래스
- 현재 잘 사용하지 않음 -> Calendar 새로운 클래스 제공
Calendar 클래스
시간, 날짜에 관한 처리를 담당하는 클래스
- 추상클래스라서 직접 객체 생성 안됨
- getInstance()메소드를 통해 Calendar 인스턴스 반환
- LocalTime : 시간 관련 클래스, LocalTime 객체는 두 개의 정적 메소드를 통해 반환
LocalTime.now(); : 현재 시간
LocalTime.of(시간,분,초); : 시간을 지정해서 출력가능
- LocalDate : 날짜 관련 클래스, LocalDate 객체도 두 개의 정적 메소드로 반환
LocalDate.now(); : 현재 날짜
LocalDate.of(년도,달,월); : 날짜를 지정해서 출력가능
- LocalDateTime : 시간, 날짜 함께 작업할 때 사용하는 클래스
LocalDateTime.now(); : 현재 날짜, 시간
LocalDateTime.of(지정날짜, 지정시간); : 지정한 날짜, 지정한 시간
- ZonedDateTime : 시간대(Time Zone)을 활용한 작업을 해야할 때 사용하는 클래스
ZonedDateTime.now(); : 현재 날짜, 시간, 지역
ZonedDateTime.of(날짜, 시간, ZoneId.of("지역")); : 지정 날짜, 시간, 지역
time 패키지의 클래스들이 가지고 있는 필드값들을 확인
- 변수명.메소드();
- .getHour(), .getMinute(), .getSecond(), .getNano(), .getYear(), .getMonth(), .getMonthValue(), .getDayOfMonth(), .getDayOfYear(), .getDayOfWeek(), .getZone(), .getOffset()
time 패키지의 클래스가 제공하는 날짜 비교 연산 메소드를 활용
- 변수명.메소드();
- .isAfter(), isBefore(), isEqual() -> 부울 값으로 출력
참고
스레드 : 프로그램 실행 단위 하나하나, 기본적으로 스레스드 한 단위씩 실행 가능
동기화 : 여러 스레드가 동시에 사용할 때 충돌이 나지 않게 도와주는 것