1. 객체 생성
클래스 변수 = new 클래스(); // 참조 변수
1) new 연산자로 인해 라이브러리 클래스 Car로 넘어간다.
2) 현재 Car 클래스에는 생성자가 없음으로 default 생성자를 통해 Car 클래스 멤버들을 초기화하여 Car 객체를 힙 영역에 생성한다.
3) new 연산자가 객체의 번지수를 받아 대입 연산자를 통해 Car 클래스 타입의 참조 변수 myCar에 저장한다.
4) myCar에는 객체의 번지수가 들어있으므로 이용하여 객체에 접근이 가능하다.
2. 생성자
생성자는 클래스와 이름이 같아야하며 반환값을 가지지 않는다(메소드와의 차이점). 프로그래머가 선언을 생략할 경우 자동으로 default 생성자(매개변수 X)로 인해 객체 생성이 가능하다. 클래스에 생성자를 선언하였을 시에는 선언된 생성자가 객체를 생성하며, 생성자는 여러 개 선언될 수 있다(오버로딩)
프로그래머가 생성자를 선언하였을 경우에는 기본 생성자를 자동으로 사용할 수 없기 때문에, 매개 변수가 없는 생성자가 필요하다면 직접 선언해줘야 한다. 또한 생성자가 여러개 있을 경우에는 매개 변수의 타입, 개수, 순서에 맞는 생성자가 사용된다.
3. this. VS this()
this는 현재 생성되고 있는 객체의 필드를 가리키는 것이다. 주로 생성자와 ㅔ소드의 매개 변수 이름이 필드와 동일한 경우, 인스턴스 멤버인 필드임을 명시한다.
this.name은 Korean 객체의 필드이고 name은 생성자의 매개변수를 말한다.
this()는 자신이 아닌 다른 생성자를 호출하며, 생성자의 첫번째 줄에 작성해야만 한다. 이러한 방식을 통해 중복 코드를 예방할 수 있다.
첫 번째와 두 번째 생성자는 초기화 내용을 가지고 있는 세 번째 생성자를 호출한다.
4. 인스턴스(instance) 멤버 VS 정적(static) 멤버
- 인스턴스 멤버 (빨간 상자)
객체를 생성한 후 사용할 수 있는 필드, 메소드
객체의 주소를 저장하고 있는 참조변수와 .(도트)연산자를 이용하여 사용
- 정적 멤버 (주황 상자)
클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드, 메소드 -> 클래스의 로딩이 끝나면 바로 사용 가능
클래스의 이름과 .연산자를 이용하여 사용
이때 클래스 변수인 정적 필드는 프로그램 실행 전 생성되어 객체 외부 클래스 영역에 존재하며 클래스가 생성 시 초기화 된다.
- 정적 메소드를 선언 시에는 그 내부에 인스턴스 필드 및 메소드 사용과 this 키워드를 사용할 수 없다. 정적 메소드에서 인스턴스 멤버를 사용하기 위해서는 객체를 생성 후 참조 변수로 접근하여야 한다.
5. 싱글톤(Singleton)
전체 프로그램에서 단 하나의 객체만 만들도록 보장하는 코딩 기법이다.
- 클래스 외부에서 new 연산자를 통해 생성자 호출을 불가하도록 생성자에 private 접근 제한자를 사용하여야 함. (4번 줄)
- 자신의 타입인 정적 필드 선언 후 자신의 객체 생성해 초기화하여야 함. (4번 줄, 7번)
- 외부에서 호출할 수 있는 getInstance() 선언해야 함. -> 정적 필드에서 참조하는 자신의 객체 리턴
외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드 이며, 단 하나의 객체를 리턴하기 때문에 obj1과 obj2는 같은 객체를 참조한다. 실제로 주소를 println을 통해 출력해보면 같은 주소가 출력된다.
6. Getter와 Setter 메소드
외부에서 객체에 마음대로 접근할 경우 객체의 무결성이 위배될 수 있기 때문에 get&&set 메소드들을 사용(보안 개념)
- Setter (setXXX) 메소드
외부의 값을 받아 필드의 값을 변경하는 것이 목적으로 매개값을 검증하여 유효한 값만 필드로 저장
- Getter (getXXX 또는 isXXX) 메소드
외부로 필드값을 전달하는 것이 목적으로 필드값을 가공해서 외부로 전달
위 예시와 같은 경우 속도는 - 값을 가질 수 없기 때문에 유효하지 않은 값이므로 0으로 값을 변경한다. 올바른 속도가 들어왔을 경우에는 해당 속도로 값을 변경할 수 있다.
7. 상속
이미 개발된 클래스를 재사용하여 새로운 클래스를 만들어 중복되는 코드를 줄일 수 있으며, 부모 클래스를 수정하면 모든 자식 클래스까지 수정되는 효과가 있다. 자식은 여러 개의 부모 클래스 상속할 수 없다는 특징이 있다.
상속을 받기 위해서는 자식 클래스 선언 시 부모 클래스를 선택하면 된다.
Class 자식클래스 extends 부모클래스 {}
*부모 클래스에서 private(내부에서만 가능)를 갖는 필드와 메소드는 상속이 되지 않는다.
*부모와 자식이 다른 패키지에 존재할 경우 default(같은 패키지에서만 가능)를 갖는 필드와 메소드도 상속되지 않는다.
1) new 연산자에 의해 자식의 생성자가 실행
2) 자식 생성자가 실행
3) 자식 생성자의 맨 첫 줄에서 자동으로 부모 생성자가 호출
4) 부모 생성자가 실행되어 부모 클래스의 멤버를 가진 객체가 heap 에 생성(0x80)되고 부모 생성자 종료
5) 부모의 주소를 저장한 객체를 생성하고 자식 생성자 종료
6) 자식의 주소를 new 연산자가 받아서 대입 연산자를 통해 참조 변수에 저장
위와 같은 과정을 통해 자식은 부모 객체를 하나처럼 사용할 수 있다. (자식 객체가 호출되어 필드, 메소드가 사용될 때 먼저 자식 클래스에 사용하기 위한 값이 있는지 확인한다. 없으면 가지고 있는 부모 객체의 주소를 이용해 부모 객체로 넘어가서 사용하게 된다.)
****** <나의 의문> ******
위 사진의 문제점. class B는 A를 상속 받지 못한다. (나의 지식이라면 B는 A의 상속을 받을 수 있는거 아닌가라고 생각했음)
내가 고려해야 했던 점들!!
1) 생성자를 프로그래머가 선언하지 않았을 경우 기본 생성자를 자동으로 생성해준다. 하지만 하나라도 생성자를 선언하였을 경우 기본 생성자를 자동으로 생성해주지 않는다.(프로그래머가 직접 선언해줘야 함.)
2) 자식 클래스로 객체를 생성할 때 자식 클래스의 생성자가 실행되고 자동으로 부모 클래스의 생성자 또한 호출된다.
위 사진과 같은 경우 자식이 부모 생성자를 호출해야 한다. 하지만 기본 생성자가 선언이 되어 있지 않고(자동으로 호출되지 못함) 그렇다고 매개변수를 갖는 생성자를 호출할 수 없기 때문에 에러가 발생한다. 에러를 해결하기 위해서는 두 가지 방법이 있다. 첫 번째는 부모 클래스에 기본 생성자를 추가하는 것, 두 번째는 매개변수를 갖는 부모 생성자를 호출하는 것이다.
첫 번째의 경우 부모 클래스에 있는 필드를 사용하지 않을 경우 상관없을 수 있지만? 사용해야 하면 좋은 방법이 아니다. 때문에 매개변수를 갖는 부모 생성자를 호출할 줄 알아야 한다! 부모 생성자를 호출할 수 있는 방법은 아래와 같다.
super() // 부모 생성자 호출
8. super() : 명시적으로부모 생성자 호출
super() 안에 매개값을 넣어 매개변수를 갖는 부모 생성자를 호출할 수 있다. 반드시 자식 생성자의 맨 첫 줄에 작성해야 한다.(자식 생성자의 맨 첫 줄에서 부모 생성자가 호출되기 때문)
9. 메소드 재정의 (Overriding / 오버라이딩)
부모 클래스의 메소드가 자식 클래스에서 사용하기에 부적합할 경우 자식 클래스에서 수정하여 사용할 수 있게 함. 매소드가 재정의될 경우 부모 객체 메소드가 숨겨져, 자식 객체에서 메소드를 호출하면 재정의된 자식 메소드가 호출된다. 다음은 메소드 재정의 방법이다.
1) 부모 메소드와 동일한 시그니처 가져야 함.
2) 접근 제한 더 강하게 재정의 할 수 없음.
3) 새로운 예외를 throws 할 수 없음.
자식 클래스 내부에서 재정의 된 부모 클래스 메소드를 호출해야 하는 경우에는 super 키워드를 통해 호출할 수 있다.
super.부모메소드();
10. 다형성
다양한 객체를 활용해 여러 실행 결과가 나오도록 하는 성질을 말함. 메소드 재정의와 타입 변환으로 구현한다.
- 자동 타입 변환(promotion)
프로그램 실행 도중 자동으로 타입 변환이 일어나는 것
부모타입 변수 = 자식타입;
위와 같은 경우 자식 자신이 생성한 필드, 메소드는 있지만 부모에게서 상속 받은 필드 및 메소드만 사용이 가능하다.
예외적으로, 메소드가 자식 클래스에서 재정의 되었을 경우 자식 클래스의 메소드가 대신 호출된다. (27번째 줄)
- 강제 타입 변환 (casting)
부모 타입을 자식 타입으로 변환하는 것. 단, 자식 타입이 부모 타입으로 자동 타입 변환한 후 다시 자식으로 변환할 때만 가능하다.
if(부모타입 instanceof 자식타입) {
자식타입 변수 = (자식타입) 부모타입_변수; }
*casting을 하면 오류가 발생할 확률이 존재하기 때문에 instanceof 연산자를 사용하여 ex) 부모타입_변수가 자식 객체를 가리키고 있는지를 확인한 후 안전하게 실행해야 한다.
11. 추상 클래스
실체 클래스(객체 생성용)들의 공통적인 특성(필드, 메소드)을 추출하여 선언한 것. 추상 클래스는 설계 규격이라고 생각하면 쉽다. 설계 규격대로 언급되어 있는 것을 토대로 실체 클래스를 작성하면 되기 때문에 시간 절약이 될 수 있다.
public abstract class 클래스 {
//필드
//생성자
//메소드 }
이러한 추상 클래스는 직접 객체를 생성할 수 없으며(main 9번 줄), 자식 객체가 생성될 때 같이 객체화 될 수 있다.
12. 추상 메소드
메소드 선언만 통일하고 실행 내용은 실체 클래스마다 달라야 하는 경우에 사용한다. 추상 클래스와 동일하게 abstract 키워드로 선언하며 중괄호에 내용이 없는 메소드이다. 때문에 하위 클래스는 사용시 재정의해서 실행 내용을 채워야 한다.
[public | protected] abstract 리턴타입 메소드이름 (매개 변수, ...) {}
*메소드가 abstract인 경우 추상 메소드를 포함하고 있는 클래스도 abstract가 되어야 한다.
'Develop' 카테고리의 다른 글
[Concept] JAVA (입출력 스트림, OutputStream, InputStream, Writer, Reader, 보조 스트림, 입출력 관련 API) (0) | 2022.07.20 |
---|---|
[Concept] JAVA (제네릭스, 컬렉션 프레임워크, Set, Map, Stack, Queue) (0) | 2022.07.04 |
[Concept] JAVA (java.lang 패키지, java.system 패키지, 동기화, 스레드) (0) | 2022.06.22 |
[Concept] JAVA (인터페이스, 중첩 클래스, 익명 객체, 예외) (0) | 2022.06.16 |
[Concept] JAVA (데이터 타입, 타입 변환, 배열, for) (0) | 2022.06.01 |