abstract 키워드 - 추상 메서드와 추상 클래스
추상 메서드란 선언부는 있지만 구현부가 없는 메서드를 말한다. 추상 메서드를 하나라도 갖고 있는 클래스는 반드시 추상 클래스여야 한다.
public class Driver2 {
public static void main(String[] args){
Animal[] animals = new Animal[5];
animals[0] = new Dog();
animals[1] = new Cat();
animals[2] = new Cow();
animals[3] = new Bird();
animals[4] = new Dolphin();
for(int i=0; i<animals.length; i++){
animals[i].sound();
}
}
}
public abstract class Animal {
abstract void sound();
}
public class Bird extends Animal{
@Override
void sound() {
System.out.println("짹짹");
}
}
동물 타입의 참조 변수를 통해 하위 클래스의 인스턴스가 가진 sound()를 호출하고 있으니 상위 클래스인 동물의 sound()는 반드시 존재해야 한다. 그런데 실수로 동물 클래스의 인스턴스를 만들고 그렇게 만들어진 동물 객체의 sound()메서드를 호출하면 난감해진다.
이경우 추상 메서드를 사용하여 메서드 선언은 있되 몸체는 없는 형태로 메서드를 구현한다.
- 추상 클래스는 인스턴스, 즉 객체를 만들 수 없다. => new 사용 불가
- 추상 클래스는 하위 클래스에게 메서드의 구현을 강제한다. 오버라이딩 강제
- 추상 메서드를 포함하는 클래스는 반드시 추상 클래스여야 한다.
생성자
- 클래스의 인스턴스, 즉 객체를 만들 때마다 new 키워드를 사용한다
- ex) Animal pororo = new Animal();
- 반환값이 없고 클래스명과 같은 이름을 가진 메서드를 객체를 생성하는 메서드라고 해서 생성자라고 한다.
- 자바가 컴파일시 자동으로 기본 생성자를 만들어준다
- 인자가 있는 생성자를 하나라도 만든다면 자바는 기본생성자를 만들지 않는다.
- 생성자는 필요한만큼 오버로딩해서 만들 수 있다.
참고
생성자로 객체를 생성하면, RDMBS에서 필드가 not null인 경우 null인 객체로 생성된다. 이를 극복하기 위해 builder 패턴을 사용한다.
클래스 생성 시의 실행 블록, static 블록
클래스의 생성자는 존재하지 않는다. 그러나 클래스가 실행될 때 스태틱 영역에 배치될 때 실행되는 코드블록이 static 블록이다.
public class Human {
static {
System.out.println("인간 클래스 레디 온");
}
}
public class Driver3 {
public static void main(String[] args){
Human rosie = new Human();
}
}
=> 인간 클래스 레디 온
public class Driver4 {
public static void main(String[] args){
System.out.println("main메서드 시작");
}
}
=> 인간 클래스 레디 온
main메서드 시작
- static 블록에서 사용할 수 있는 속성과 메서드는 당연히 static멤버 뿐이다. 객체 멤버는 클래스가 static영역에 자리 잡은 후에 객체 생성자를 통해 힙에 생성된다.클래스의 static블록이 실행되고 있을때는 해당 클래스의 객체는 하나도 존재하지 않기 때문에 static블록에서는 객체 멤버에 접근할 수 없는 것이다.
public class Driver4 {
public static void main(String[] args){
System.out.println("main메서드 시작");
Human rosie = new Human();
}
}
=> main메서드 시작
인간 클래스 레디 온
public class Driver4 {
public static void main(String[] args){
System.out.println("main메서드 시작");
Human rosie = new Human();
Human peggy = new Human();
}
}
=> main메서드 시작
인간 클래스 레디 온
- 인간 클래스의 인스턴스를 여러개 만들어도 인간 클래스의 static블록은 단 한번만 실행된다
- 클래스 정보는 해당 클래스가 코드에서 맨 처음 사용될 때, T메모리의 스태틱 영역에 로딩되며, 이때 단 한번 해당 클래스의 static블록이 실행된다.
******* 클래스가 제일 처음 사용되는 3가지 경우 = 클래스 로더에 의해 해당 클래스가 로딩되는 시점
- 클래스의 정적 속성을 사용시
- 단, final로 선언되면 안됨
- 클래스의 정적 메서드를 사용시
- 클래스의 인스턴스를 최초로 생성 시
=> 프로그램 실행 시 바로 클래스들의 정보를 T메모리의 static영역에 로딩하지 않고 해당 클래스가 처음 사용시 로딩되는 이유는 스태틱 영역도 메모리이기 때문이다. 메모리는 최대한 늦게 사용을 시작하고, 최대한 빨리 반환하는 것이 정석이다.
자바는 스태틱 영역에 한번 올라가면 프로그램 종료시까지 해당 메모리를 반환할 수 없지만 그럼에도 불구하고 최대한 늦게 로딩함으로써 메모리 사용을 늦추기 위해서다!
final 키워드
최종, 마지막이라는 의미로 클래스, 변수, 메서드에 final을 표기할 수 있다.
final 과 클래스
public final class Cat {
}
- 상속 불가
final 과 변수
- 생성과 동시에 초기화
- 변경 불가능한 상수가 된다
public final class Cat {
final static int s_var1 = 1;
final static int s_var2;
final int o_var1 = 1;
final int o_var2;
static {
s_var2=2;
// s_var2=4;
}
Cat(){
o_var2=2;
//o_var2=4;
final int l_var1=1;
final int l_var2;
l_var2=2;
}
}
- 정적 상수는 선언 시에, 또는 정적 생성자에 해당하는 static 블록 내부에서 초기화 가능하나 재할당은 불가
- 객체 상수는 선언 시에, 또는 객체 생성자 또는 인스턴스 블로겡서 초기화 가능
- 지역 상수는 선언 시에, 또는 최초 한번만 초기화 가능
final 과 메서드
- 오버라이딩 불가
instanceof 연산자
- 만들어진 객체가 특정 클래스의 인스턴스인지 묻는 연산자
- true or false로 결과 반환
interface 키워드와 implements 키워드
- 인터페이스는 public 추상메서드와 public 정적 상수만 가질 수 있기에, 메서드에 public과 abstract 속성에 public, static, final을 붙히지 않아도 자동으로 자바가 붙여준다
interface Speakable {
double PI = 3.14159;
final double absoluteZeroPoint = -275.15;
void sayYes();
}
public interface Speakable {
public static final double PI = 3.14159;
public static final double absoluteZeroPoint = -275.15;
public abstract void sayYes();
}
- 인터페이스의 메서드가 추상메서드인 이유는 몸체가 없다
public class Driver5 {
public static void main(String[] args){
// Speakable.PI = 3.14;
}
}
- 변수에 값을 할당할 수 없다는 것은 상수, 즉 final 변수라는 의미
- 클래스명으로 접근할 수 있는 속성은 정적 속성
참고
자바 8이전까지의 인터페이스는 정적 상수와 객체 추상 메서드만 가질 수 있었던 것에 반해 자바 8부터는 디폴트 메서드라고 하는 객체 구상메서드와 정적 추상 메서드를 지원할 수 있게 바뀌었다.
this 키워드
public class Penguin{
int var =0;
void test(){
int var =20;
System.out.println(var);
System.out.println(this.var);
}
}
class Driver{
public static void main(String[] args){
Penguin p = new Penguin();
p.test();
}
}
20
10
- 지역 변수와 속성(객체변수, 정적 변수)의 이름이 같은 경우 지역 변수가 우선시한다.
- 객체 변수와 이름이 같은 지역 변수가 있는 경우 객체 변수를 사용하려면 this 접두사로 사용한다.
- 정적 변수와 이름이 같은 지역 변수가 있는 경우 정적 변수를 사용하려면 클래스명을 접두사로 사용한다.
super 키워드
단일 상속만을 지원하는 자바에서 바로 위 상위 클래스의 인스턴스를 지칭하는 키워드
class Book {
void mehtod(){
System.out.println("책");
}
}
class SpringBook extends Book{
void method(){
super.mehtod();
System.out.println("스프링 책");
}
}
- 바로 위의 상위 클래스 인스턴스에는 접근할 수 있지만, super.super 형태로 상위의 상위 클래스의 인스턴스에는 접근 불가
[참고]
스프링 입문을 위한 자바 객체 지향의 원리와 이해
'JAVA > 객체지향의 원리' 카테고리의 다른 글
[객체지향의 원리와 이해 3] 자바와 객체 지향 (0) | 2023.06.26 |
---|---|
[객체지향의 원리와 이해 2] 자바의 절차적 / 구조적 프로그래밍 (0) | 2023.06.26 |
[객체지향의 원리와 이해 1] 사람을 사랑한 기술 (0) | 2023.06.26 |
[OOP] interface / 인터페이스 (0) | 2022.09.07 |
[OOP] abstract / 추상화 (0) | 2022.09.05 |