지금까지..
클래스를 선언해놓고, 객체를 만들어 쓰고 싶을때마다 간단히 클래스 이름으로 생성자를 호출하곤 했다.
그런데 클래스 이름이 없는 객체가 있다.
-->익명(anonymous) 객체
<익명 객체 만드는 조건>
ㅇ어떤 클래스를 상속한다.
ㅇ어떤 인터페이스를 구현한다.
익명 객체를 생성할 때는 다음과 같이 클래스 이름이 없다.
[상속]
부모클래스 변수 = new 부모클래스() { ... };
어어!! 부모클래스이름만 표시가 되네..
[구현]
인터페이스 변수 = new 인터페이스() { ... };
헉... 구현 객체가 이름이 없어서 인터페이스명만 표시하네...
>>상속 : 부모 클래스 변수는 이름이 없는 자식 객체를 참조한다.
>>구현 : 인터페이스 변수는 이름이 없는 구현 객체를 참조한다.
이 순서로 학습한다.
1. 익명 자식 객체 생성
2. 익명 구현 객체 생성
3. 익명 객체의 로컬 변수 사용
1. 익명 자식 객체 생성
일단..
자식클래스를 명시적으로 선언했던 이유는 : 어디서건 이미선언된 자식클래스로 간단히 객체를 생성해 사용하기 위함.
-->재사용성이 높다고 한다.
그러나!! -->재사용되지 않을 자식 클래스라면
-->오로지 특정 위치에서 사용할 경우라면!
굳이 자식 클래스를 명시적으로 선언할 필요가 없다.. 이곳저곳 객체생성할 것이 아니니까!! 명시적으로 선언할 필요가 없다.
이럴 경우 "익명 자식 객체"를 생성해 사용하게 되는 것이다.
ㄴ익명 자식 객체를 생성하는 방법
부모클래스 [필드|변수] = new 부모클래스(매개값, ...) {
//필드
//메소드
};
주의!! 중괄호 끝날때 세미콜론 꼭 붙여야 한다. 저 덩어리가 하나의 실행문이다.
부모클래스(매개값, ...) { ... }; --> 부모클래스를 상속해서 중괄호와 같이 자식클래스를 선언하라는 뜻이다.
저어기 new 연산자는 해당 내용의 자식클래스를 객체로 생성한다.
부모클래스(매개값, ...) : 부모 생성자를 호출한다. so 매개값은 부모 생성자 매개변수에 맞춘다.
중괄호 내부 : 자식 객체의 필드or메소드 선언 / 부모클래스에 대한 오버라이딩 (<-메소드 재정의는 흔하다)
익명자식클래스와 일반 클래스의 차이점 : 생성자를 선언할 수가 없다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
예시 세개를 학습할거다.
ㅇ필드의 초기값에 익명자식객체 생성해 넣는거,
ㅇ메소드 내부에서 로컬 변수 초기값에 익명자식 객체 생성해 넣는거,
ㅇ메소드 매개변수가 부모타입일 때 익명자식객체 생성해 매개값에 넣는거
선언, 호출부분을 작성할 때에는
중괄호까지 하나의 세트라고 보자.
중괄호까지 하나의 실행 코드기 때문에 꼭 세미콜론 넣는 것을 헷갈리지 말자.
익명자식객체 선언하는 방법 때문에 조금 길어졌을 뿐!! 하나의 실행 코드다.
세미콜론을 잊지 말자.
익명자식객체에 외부에서 접근할 수 없다.
익명자식객체는 부모타입에 대입되어서 부모타입에서 선언된 것만 사용 가능하다.
그러므로 익명 자식 객체는 부모 것 외에는 접근 못한다. 바깥클래스의 필드나 메소드에 접근을 못 한다.
A클래스의 필드 field
parentMethod()는 field에서 참조가 가능하다. (parentMethod() field로 접근할 수 있다.)
하지만 childField, childMethod()는 field에서 참조가 불가능하다.
익명자식객체는 부모의 메소드를 재정의한 메소드 등 부모 관련된 것에만 접근 가능하다.
저 익명자식객체에 선언된 childField랑 childMethod()는 재정의한 메소드인 parentMethod()내부에서 사용이 가능하다.
(즉, A클래스의 필드에서 익명자식객체의 필드와 메소드를 참조할 수 없다.)
(익명자식객체의 필드와 메소드는 A클래스의 필드에 접근할 수 없다.)
<<익명자식객체 익히기>>
2. 익명 구현 객체 생성
이번에는 인터페이스 관련
인터페이스 타입의 필드/ 변수를 선언하고
그 인터페이스를 구현한
구현 객체를 초기값으로 대입하는 경우를 보자
이것도 마찬가지로 지금까지 해온 구현 객체 대입을 잠깐 살펴보면,
우리는 명시적으로 구현 클래스를 선언했고, 이미 선언된 구현 클래스를 통해 어디서든지 간단히 객체를 생성해서 사용해왔다. (재사용성이 높다)
하지만 지금 우리가 볼 것은 익명 구현 객체이다
>>구현클래스가 재사용 될 일 없고
>>오직 특정 위치에서만 사용할 거다??
>>그럼 구현 클래스를 굳이 명시적으로 선언할 필요 없다.
익명 구현 객체는 다음과 같이 생성한다.
익명 자식객체 생성할 때랑 마찬가지로
역시 구현객체 이름이 없으니까 인터페이스명만 보인다
인터페이스 [필드|변수] = new 인터페이스() {
//인터페이스에 선언된 추상 메소드의 실체 메소드 선언
//필드
//메소드
};
인터페이스() { ...} : 인터페이스를 구현해서 중괄호 내용과 같이 클래스를 선언하라는 뜻!!!
중괄호 안에는 반드시!! 인터페이스에 선언된 모든 추상 메소드의 실체 메소드를 작성해야 한다!!
재정의 그것이 구현 객체의 임무니까 !! >.< (안하면 컴파일 에러)
+추가로 필드, 메소드를 선언할 수 있으며, 실체 메소드에서만 사용 가능하다. 외부사용 불가!
++아까 익명자식객체 배울 때도 익명자식객체에 정의된 필드와 메소드는 실체 메소드에서만 사용 가능했다.
역시 중괄호 끝에는 세미콜론이 붙어야 한다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
아까 한 것과 비슷하게
예시 세개를 학습할거다.
ㅇ필드의 초기값에 익명구현객체 생성해 넣는거,
ㅇ메소드 내부에서 로컬 변수 초기값에 익명구현객체 생성해 넣는거,
ㅇ메소드 매개변수가 인터페이스타입일 때 익명구현객체 생성해 매개값에 넣는거
1. 필드 초기값에 익명구현객체 생성해 대입하기
2. 메소드 내부 로컬 변수 초기값으로 익명구현객체 생성해 대입하기
3. 메소드의 인터페이스타입매개변수에 익명구현객체 생성해 매개값으로 대입하기
이제 실습을 통해 익명구현 객체를 익혀보자.
<<익명 구현 객체 익히기>>
<<익명객체구현 이용하는 방법 익히기>>
윈도우/안드로이드 등의 UI프로그램에서 '버튼의 클릭 이벤트를 처리'하기 위해
익명 구현 객체를 이용하는 방법을 보여주는 실습 코드를 작성하며 공부해보자.
3. 익명 객체의 로컬 변수 사용
메소드의 매개변수나 로컬변수를 익명 객체 내부에서 사용하는게 문제다.
메소드가 사라지면 매개변수, 로컬변수는 스택 메모리에서 사라져버리기 때문이다..
익명 객체에서 지속적으로 사용하지 못한다..
자바는 이 문제를 해결하기 위해 컴파일할 때 (저번에 살짝 본 내용)
익명 객체에서 사용하는 매개변수, 로컬변수의 값을 "익명객체 내부에 복사해두고" 사용한다.
-->매개변수, 로컬변수 값이 중간에 달라지면 안 되므로, 매개변수, 로컬변수를 final로 선언할 것을 요구한다.
자바7이전: final을 명시해야 했음
자바8이후: final 쓰지 않아도 final의 특성을 부여함.
<<예제로 익히기>>
ㄴ매개 변수와 로컬 변수가 익명객체내부에서 사용될 때 final특성을 가짐을 볼 수 있다.
확인문제
01.
02.
03.
'JAVA' 카테고리의 다른 글
[혼자 공부하는 자바] 7/19 10-2 [예외 처리] (0) | 2020.07.19 |
---|---|
[혼자 공부하는 자바] 7/17 10-1 [예외 처리] [예외 클래스] [일반예외] [실행예외] (0) | 2020.07.17 |
객체지향 프로그래밍 간단한 개념 정리 / 특징 (0) | 2020.07.14 |
[2주차] 기본미션 + 선택미션 [혼공단] [혼공자] (0) | 2020.07.14 |
[혼자 공부하는 자바] 7/13 9-1 [중첩 클래스와 중첩 인터페이스] (0) | 2020.07.13 |