1221 - 1227
1221
다형성이란?
객체지향에서는 ‘여러 가지 형태를 가질 수 있는 능력’
자바에서는 조상클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조할 수 있도록 함
ex) Tv와 CaptionTv클래스가 서로 상속 관계일 때,
Tv t = new CationTv();
- 실제 인스턴스가 CaptionTv 타입이라 할지라도, 참조 변수 t로는 CaptionTv 인스턴스의 모든 멤버를 사용할 수 없다.
- Tv타입의 참조변수로는 CaptionTv 인스턴스 중에서 Tv 클래스의 멤버들만 사용할 수 있다.
- 같은 타입의 인스턴스라도 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.
반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조하는 것은 가능할까?
CaptionTv c = new Tv(); //컴파일 에러
- 실제 인스턴스인 Tv의 멤버 개수보다 참조변수 c가 사용할 수 있는 멤버 개수가 더 많기 때문
- 자손타입의 참조변수로 조상타입의 인스턴스를 참조하는 것은 존재하지 않는 멤버를 사용하고자 할 가능성이 있으므로 허용하지 않음
- 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.
조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있다
반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다
1222
인터넷 네트워크
http메서드를 학습하기 전에 기본적으로 짚고 넘어가야 할 인터넷 네트워크에 대한 지식들을 정리해보았다.
인터넷 통신
인터넷에서 컴퓨터 둘은 어떻게 통신할까?
- 클라이언트와 서버가 통신하기 위해 여러 노드를 타고 데이터가 이동한다.
- 그러기 위한 가장 기본적인 통신 규약이 IP이다.
IP(인터넷 프로토콜)
- 클라이언트와 서버가 통신하기 위해서는 기본적으로 IP주소가 있어야 한다. Ex) 100.100.100.1
IP 역할
- 지정한 IP 주소(IP Address)에 데이터 전달
- 패킷(Packet)이라는 통신 단위로 데이터 전달
IP 패킷 정보
출발지 IP, 목적지 IP, 기타…
IP프로토콜의 한계
- 비연결성
-> 패킷을 받을 대상이 없거나 서비스 불능 상태여도 패킷 전송 - 비신뢰성
-> 중간에 패킷이 사라지거나, 순서대로 오지 않는 것을 보장하지 않음 - 프로그램 구분
-> 같은 IP를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이면 구분하지 못함
TCP UDP
인터넷 프로토콜 스택의 4계층
- 애플리케이션 계층 - HTTP, FTP
- 전송 계층 - TCP, UDP
- 인터넷 계층 - IP
- 네트워크 인터페이스 계층
TCP/IP 패킷 정보
- TCP - 출발지 PORT, 목적지 PORT, 전송 제어, 순서, 검증 정보…
- IP - 출발지 IP, 목적지 IP, 기타…
- 이러한 정보들을 가지고 IP프로토콜에서의 문제들을 해결한다
TCP 특징
전송 제어 프로토콜(Transmission Control Protocal)
- 연결 지향 - TCP 3 way handshake (가상연결)
- 데이터 전달 보증
- 순서 보장
-> 신뢰할 수 있는 프로토콜
TCP 3 way handshake
- 클라이언트 -> 서버 - SYN
- 서버 -> 클라이언트 - SYN+ACK
- 클라이언트 -> 서버 - ACK
- 데이터 전송
물리적으로 연결이 된 것이 아니라, 논리적으로 연결이 된 것이다.
SYN: 접속 요청
ACK: 요청 수락
3.에서 ACK와 함께 데이터 전송 가능
UDP 특징
사용자 데이터그램 프로토콜(User Datagram Protocol)
- 기능이 거의 없음
- 연결 지향, 데이터 전달 보증, 순서 보장 모두 X
- 데이터 전달 및 순서가 보장되지 않지만, 단순하고 빠름
- IP와 거의 같다. + PORT + 체크섬(메시지에 대해 제대로 받는지 검증) 정도만 추가
- 애플리케이션에서 추가 작업 필요
PORT
서버 안에서 돌아가는 애플리케이션을 찾는 것
같은 IP 내에서 프로세스를 구분
ex) 한 컴퓨터에서 게임, 화상통화, 웹 브라우저를 동시에 사용할 때 각각 포트번호를 다르게 해서 통신이 원활하게 한다.
- 0 ~ 65535 할당 가능
- 0 ~ 1023은 잘 알려진 포트, 사용하지 않는 것이 좋음
DNS
IP주소의 문제점
- IP 주소는 기억하기 어렵다.
- IP 주소는 변경될 수 있다.
DNS
도메인 네임 시스템(Domain Name System)
- 도메인 명을 IP 주소로 변환
-> 전화번호부와 같은 역할
DNS 사용
- 도메인 명을 url에 작성한다.
- DNS 서버에서 도메인 명을 IP 주소로 변환하여 응답해준다.
- 받은 IP 주소로 서버에 접속한다.
-> 2가지 문제점을 동시에 해결
1223
URI와 웹 브라우저 요청 흐름
URI(Uniform Resource Identifier)
URI는 로케이터(locator), 이름(name) 또는 둘 다 추가로 분류될 수 있다.
URI 단어 뜻
- Uniform : 리소스 식별하는 통일된 방식
- Resource : 자원, URI로 식별할 수 있는 모든 것(제한 없음)
- Identifier : 다른 항목과 구분하는데 필요한 정보
URL, URN
- URL - Locator : 리소스가 있는 위치를 지정
- URN - Name : 리소스에 이름을 부여
- 위치는 변할 수 있지만 이름은 변하지 않는다.
- URN 이름만으로 실제 리소스를 찾을 수 있는 방법이 보편화 되지 않음
URL 전체 문법
schemme://[userinfo@]host[:port][/path][?query][# fragment]
ex) https://www.google.com:443/search?q=hello&hl=ko
- 프로토콜
- 호스트명
- 포트 번호
- 패스
- 쿼리 파라미터
scheme
- 주로 프로토콜 사용
- 프로토콜 : 어떤 방식으로 자원에 접근할 것인가 하는 약속 규칙
- http는 80포트, https는 443 포트를 주로 사용, 포트는 생략 가능
userinfo
- URL에 사용자정보를 포함해서 인증
- 거의 사용하지 않음
host
- 호스트명
- 도메인명 또는 IP 주소를 직접 사용 가능
PORT
- 접속 포트
- 일반적으로 생략, 생략시 http는 80, https는 443
path
- 리소스 경로, 계층적 구조
query
- key=value 형태
- ?로 시작, &로 추가 가능
- query parameter, query string 등으로 불림, 웹서버에 제공하는 파라미터
fragment
- html 내부 북마크 등에 사용
- 서버에 전송하는 정보 아님
웹 브라우저 요청 흐름
- resource 요청 시, 웹 브라우저가 HTTP 메시지 생성
- SOCKET 라이브러리를 통해 TCP/IP로 3way handshake를 실행해 서버와 연결한다.
- 운영체제 TCP/IP 계층으로 데이터 전송을 하기 위해 데이터를 전달한다.
- HTTP 메시지가 포함된 TCP/IP 패킷을 생성한다.
- 패킷 정보가 인터넷으로 흘러간다.
- 서버에 요청 패킷이 도착하여 패킷 껍데기는 버리고 HTTP 메시지를 서버가 해석한다.
- HTTP 응답 메시지를 마찬가지 방식으로 패킷을 생성하여 응답 패킷을 전달한다.
- 수 많은 노드들을 통해서 응답 패킷이 도착하게 되면 웹 브라우저가 HTML 렌더링하여 화면에 보여준다.
1224
참조변수의 형변환
- 서로 상속관계에 있는 클래스사이에서는 참조변수도 형변환이 가능하다.
- 자손타입의 참조변수를 조상타입의 참조변수로, 조상타입의 참조변수를 자손타입의 참조변수로의 형변환만 가능
자손타입 -> 조상타입(Up-casting) : 형변환 생략가능
조상타입 -> 자손타입(Down-casting) : 형변환 생략불가
- 자손타입의 참조변수를 조상타입의 참조변수로 형변환 하는 것은 참조변수가 다룰 수 있는 멤버의 개수가 실제 인스턴스가 갖고 있는 멤버의 개수보다 적을 것이 분명하므로 문제가 되지 않는다. 그래서 형변환을 생략할 수 있다.
- 형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니기 때문에 참조변수의 형변환은 인스턴스에 아무런 영향을 미치지 않는다. 단지 참조변수의 형변환을 통해서, 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 범위(개수)를 조절하는 것 뿐이다.
public class CastingTest {
public static void main(String[] args) {
Car car = new Car();
Car car2 = null;
FireEngine fe = null;
car.drive();
fe = (FireEngine) car; //컴파일은 OK. 실행 시 에러가 발생
fe.drive();
car2 = fe;
car2.drive();
}
}
- 참조변수 car가 참조하고 있는 인스턴스가 Car타입의 인스턴스이기 때문에 조상 타입의 인스턴스를 자손타입의 참조변수로 참조하는 것은 허용되지 않는다.
- 컴파일 시에는 참조변수간의 타입만 체크하기 때문에 실행 시 생성될 인스턴스의 타입에 대해서는 전혀 알지 못한다.
- 서로 상속관계에 있는 타입간의 형변환은 양방향으로 자유롭게 수행될 수 있으나, 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않는다.
- 그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것은 중요하다.
instance 연산자
- 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 instanceof 연산자를 사용한다.
- 왼쪽에는 참조변수를 오른쪽에는 타입(클래스명)이 피연산자로 위치한다.
- 실제 인스턴스와 같은 타입의 instanceof연산 이외에 조상타입의 instanceof연산에도 true를 결과로 얻는다.
- 어떤 타입에 대한 instanceof연산의 결과가 true라는 것은 검사한 타입으로 형변환이 가능하다는 것을 뜻한다
1225
추상 클래스(abstract class)
추상클래스란?
미완성 설계도
-> 클래스가 미완성이라는 것은 멤버의 개수에 관계된 것이 아니라, 단지 미완성 메서드(추상메서드)를 포함하고 있다는 의미
- 상속을 통해서 자손클래스에 의해서만 완성될 수 있다.
- 자체로는 클래스로서의 역할을 다 못하지만, 새로운 클래스를 작성하는데 있어서 바탕이 되는 조상클래스로서 중요한 의미를 갖는다.
- 키워드 ‘abstract’를 붙이기만 하면 된다.
- 이렇게 함으로써 클래스 선언부를 보고 이 클래스에는 추상메서드가 있으니 상속을 통해서 구현해주어야 한다는 것을 알 수 있다.
abstract class 클래스이름 {
...
}
- 추상클래스는 추상메서드를 포함하고 있다는 것을 제외하고는 일반클래스와 전혀 다르지 않다.
추상메서드를 포함하고 있지 않은 클래스에도 미워드 ‘abstract’를 붙여서 추상클래스로 지정할 수도 있다.
추상메서드가 없는 완성된 클래스라 할지라도 추상클래스로 지정되면 클래스의 인스턴스를 생성할 수 없다.
추상메서드(abstract method)
선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔 메서드
-> 설계만 해 놓고 실제 수행될 내용은 작성하지 않았기 때문에 미완성 메서드
- 메서드의 내용이 상속받는 클래스에 따라 달라질 수 있기 때문에 조상 클래스에서는 선언부만 작성하고, 실제 내용은 상속받는 클래스에서 구현하도록 비워 두는 것
- 추상메서드 역시 키워드 ‘abstract’를 앞에 붙여 주고, 구현부가 없으므로 괄호{} 대신 문장의 끝을 알리는 ‘;’을 적어준다.
/* 주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다. */
abstract 리턴타입 메서드이름();
- 추상클래스를 상속받는 자손클래스는 오버라이딩을 통해 추상메서드를 모두 구현해주어야 한다.
- 하나라도 구현하지 않는다면, 자손클래스 역시 추상클래스로 지정해 주어야 한다.
- 추상메서드 대신, 아무 내용도 없는 메서드로 작성할 수도 있다.
- 그래도 굳이 추상메서드로 선언하는 이유는 자손 클래스에서 추상메서드를 반드시 구현하도록 강요하기 위해서이다.
추상클래스의 작성
추상화 : 클래스간의 공통점을 찾아내서 공통의 조상을 만드는 작업
구체화 : 상속을 통해 클래스를 구현, 확장하는 작업
- 상속계층도를 따라 내려갈수록 클래스는 점점 기능이 추가되어 구체화의 정도가 심해지며, 올라갈수록 추상화의 정도는 심해진다고 할 수 있다.
abstract class Unit { //추상클래스
int x, y;
abstract void move (int x, int y);
void stop() {}
}
class Marine extends Unit {
void move (int x, int y) { //추상메서드 구현 }
void stimPack() {}
}
class Tank extends Unit {
void move (int x, int y) { //추상메서드 구현 }
void changeMode() {}
}
- 클래스들의 공통부분을 뽑아내서 Unit클래스를 정의하고 이로부터 상속받도록 하였다.
- move메서드의 선언부는 같지만 이동하는 방법이 서로 달라서 추상메서드로 정의한다.
- 최대한의 공통부분을 뽑아내기 위한 것이기도 하지만, 모든 유닛은 이동할 수 있어야 하므로 Unit클래스에는 move메서드가 반드시 필요한 것이기 때문
- stop메서드는 모두 공통적이지만, move메서드가 추상메서드로 선언된 것에는, Unit클래스를 상속받아서 작성되는 클래스는 move메서드를 자신의 클래스에 알맞게 반드시 구현해야 한다는 의미가 담겨있는 것이기도 하다.
Unit[] group = new Unit[2];
group[0] = new Marine();
group[1] = new Tank();
for(int i=0; i<group.length; i++)
group[i].move(100, 200);
- 공통조상인 Unit클래스 타입의 참조변수 배열을 통해서 서로 다른 종류의 인스턴스를 하나의 묶음으로 다룰 수 있다.
- 메서드는 참조변수의 타입에 관계없이 실제 인스턴스에 구현된 것이 호출되기 때문에 Unit클래스 타입의 참조변수로 move메서드 호출이 가능하다.
- 모든 클래스의 조상인 Object클래스 타입의 배열로도 서로 다른 종류의 인스턴스를 묶어서 다룰 수 있지만, move메서드가 정의되어 있지 않기 때문에 호출하는 부분에서 에러가 발생한다.
-> 참조변수는 리모콘 역할
1226
인터페이스(interface)
인터페이스란?
추상 메서드의 집합
- 추상클래스보다 추상화 정도가 높아서 추상클래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다.
- 오직 추상메서드와 상수만을 멤버로 가질수 있다.
-> 다른 클래스를 작성하는데 도움 줄 목적으로 작성
추상클래스 vs 인터페이스
추상클래스를 부분적으로 완성된 ‘미완성 설계도’라고 한다면, 인터페이스는 구현된 것은 아무 것도 없고 밑그림만 그려져 있는 ‘기본 설계도’라 할 수 있다.
인터페이스의 작성
interface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름(매개변수목록);
}
일반적인 클래스의 멤버들과 달리 인터페이스의 멤버들은 다음과 같은 제약사항이 있다
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.
- 단, static메서드와 디폴트 메서드는 예외(JDK 1.8부터)
-> 모든 멤버에 예외없이 적용되는 사항이기 때문에 생략할 수 있는 것이며, 편의상 생략하는 경우가 많다.
인터페이스의 상속
- 인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 다르게 다중상속이 가능하다.
- 클래스의 상속과 마찬가지로 자손 인터페이스는 조상 인터페이스에 정의된 멤버를 모두 상속받는다.
인터페이스는 클래스와 달리 Object클래스와 같은 최고 조상이 없다.
인터페이스의 구현
- 인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며, 자신에 정의된 초상메서드의 몸통을 만들어주는 클래스를 작성해야 한다.
- 단, 인터페이스는 구현한다는 의미의 키워드 ‘implements’를 사용한다.
- 구현하는 인터페이스의 메서드 중 일부만 구현한다면, abstract를 붙여서 추상클래스로 선언해야 한다.
- 상속과 구현을 동시에 할 수도 있다.
인터페이스의 이름에는 주로 Fightable과 같이 ‘~을 할 수 있는’의 의미인 ‘able’로 끝나는 것들이 많은데, 그 이유는 어떠한 기능 또는 행위를 하는데 필요한 메서드를 제공한다는 의미를 각종하기 위해서이다.
- 인터페이스를 구현한 클래스는 인터페이스로부터 상속받은 추상 메서드를 구현하기 때문에 인터페이스도 조금은 다른 의미의 조상이라고 할 수 있다.
- 인터페이스에서 ‘public abstract’가 생략되어 있는 경우가 많은데, 오버라이딩 할 때는 조상의 메서드보다 넓은 범위의 접근 제어자를 지정해야 하므로 이를 구현하는 클래스에서는 구현하는 메서드의 접근 제어자를 반드시 public으로 해야 한다.
인터페이스를 이용한 다중상속
- 두 조상으로부터 상속받는 멤버 중에서 멤버변수의 이름이 같거나 메서드의 선언부가 일치하고 구현 내용이 다르다면 자손 클래스는 어느 조상의 것을 상속받게 되는 것인지 알 수 없다.
- 자바에서는 단점이 더 크다고 판단하였기에 다중상속을 허용하지 않는다.
- 인터페이스는 static상수만 정의할 수 있어서 조상클래스의 멤버변수와 충돌하는 경우가 거의 없고 충돌된다 하더라도 클래스 이름을 붙여서 구분이 가능하다.
- 그리고 추상메서드는 구현내용이 전혀 없으므로 조상클래스의 메서드와 선언부가 일치하는 경우에는 조상클래스 쪽의 메서드를 상속받으면 된다.
- 그러나 이렇게 하면 상속받는 멤버의 충돌은 피할 수 있지만, 다중상속의 장점을 잃게 된다.
- 만일 두 개의 클래스로부터 상속을 받아야 할 상황이라면, 두 조상클래스중 비중이 높은 쪽을 선택하고 다른 한쪽은 클래스 내부에 멤버로 포함시키는 방식을 사용하거나 어느 한쪽의 필요한 부분을 뽑아서 인터페이스로 만든 다음 구현하도록 한다
인터페이스를 이용한 다형성
인터페이스 역시 클래스의 조상이라고 할 수 있으므로 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있고, 인터페이스 타입으로 형변환도 가능하다.
- 따라 인터페이스는 다음과 같이 메서드의 매개변수 타입으로 사용 될 수 있다.
void attack(Fightable f){
//...
}
- 인터페이스 타입의 매개변수가 갖는 의미는 메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는 것
- 예를 들어, attack메서드를 호출할 때는 매개변수로 Fightable 인터페이스를 구현한 클래스의 인스턴스를 넘겨주어야 한다.
- 메서드의 리턴타입으로 인터페이스의 타입을 지정하는 것 역시 가능하다.
Fightable method() {
Fighter f = new Fighter();
return f;
}
- 리턴 타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
1227
내부클래스
내부 클래스란?
클래스 내에 선언된 클래스
내부클래스의 장점
- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
- 코드의 복잡성을 줄일 수 있다(캡슐화).
class A { //외부클래스
class B { //내부클래스
}
}
- 이 때 내부클래스인 B는 A를 제외하고는 잘 사용되지 않는 것이어야 한다.
내부클래스의 종류와 특징
- 내부 클래스의 종류는 변수의 선언위치에 따른 종류와 같다.
- 변수를 선언하는 것과 같은 위치에 선언할 수 있으며, 선언 위치에 따라 인스턴스 내부클래스, 스태틱 내부클래스, 지역 내부클래스로 나뉜다.
- 각 내부 클래스의 선언위치에 따라 같은 선언위치의 변수와 동일한 유효범위와 접근성을 갖는다.
내부 클래스의 제어자와 접근성
- 내부 클래스가 외부 클래스의 멤버와 같이 간주되고, 인스턴스멤버와 static멤버 간의 규칙이 내부 클래스에도 똑같이 적용
- 내부클래스도 클래스이기 때문에 abstract나 final과 같은 제어자를 사용할 수 있을 뿐만 아니라, 멤버변수들처럼 private, protected과 접근제어자도 사용이 가능하다.
- 내부 클래스 중에서 스태틱 클래스만 static멤버를 가질 수 있다.
- 다만 final과 static이 동시에 붙은 변수는 상수이므로 모든 내부 클래스에서 정의가 가능
- 내부 클래스와 외부 클래스에 선언된 변수의 이름이 같을 때 변수 앞에 ‘this’또는 ‘외부 클래스명.this’를 붙여서 서로 구별할 수 있다.
- 인스턴스클래스는 외부 클래스의 인스턴스멤버를 객체생성 없이 바로 사용할 수 있지만, 스태틱 클래스는 외부 클래스의 인스턴스 멤버를 객체생성 없이 사용할 수 없다.
- 인스턴스클래스는 스태틱 클래스의 멤버들을 객체생성 없이 바로 사용할 수 있지만, 스태틱 클래스는 인스턴스 클래스의 멤버를 객체생성 없이 사용할 수 없다.
- 인스턴스 클래스는 외부 클래스의 private멤버도 접근 가능하다.
- 지역 클래스는 외부 클래스의 인스턴스 멤버와 static멤버를 모두 사용할 수 있으며, 메서드에 정의된 지역변수도 사용할 수 있다.
- 단, final이 붙은 지역변수만 접근 가능한데, 메서드가 수행을 마쳐서 지역변수가 소멸된 시점에도, 지역클래스의 인스턴스가 소멸된 지역변수를 참조하려는 경우가 발생할 수 있기 때문이다.
JDK 1.8부터 지역 클래스에서 접근하는 지역 변수 앞에 final을 생략할 수 있게 바뀌었다. 컴파일러가 자동으로 붙여주는 것이라 해당 변수의 값이 바뀌는 문장이 있으면 컴파일 에러가 발생한다.
class Outer {
class InstanceInner {
int iv = 100;
}
static class StaticInner {
int iv =200;
static int cv = 300;
}
void myMethod() {
class LocalInner {
int iv = 400;
}
}
}
public class InnerEx {
public static void main(String[] args) {
Outer oc = new Outer(); //인스턴스클래스의 인스턴스를 생성하려면 외부클래스의 인스턴스를 먼저 생성해야 한다.
Outer.InstanceInner ii = oc.new InstanceInner();
System.out.println("ii.iv =: " + ii.iv);
System.out.println("Outer.StaticInner.cv : " + Outer.StaticInner.cv);
//스태틱 내부클래스의 인스턴스는 외부 클래스를 먼저 생성하지 않아도 된다.
Outer.StaticInner si = new Outer.StaticInner();
System.out.println("si.iv : " + si.iv);
}
}
- 컴파일 했을 때 생성되는 파일명은 ‘외부 클래스명$ 내부 클래스명.class’형식
- 지역내부 클래스는 다른 메서드에 같은 이름의 내부 클래스가 존재할 수 있기 때문에 내부 클래스명 앞에 숫자가 붙는다.
익명 클래스(anonymous class)
클래스의 선언과 객체의 생성을 동시에 하기 때문에 단 한번만 사용될 수 있고 오직 하나의 객체만을 생성할 수 있는 일회용 클래스
new 조상클래스이름() {
//멤버 선언
}
또는
new 구현인터페이스이름() {
//멤버 선언
}
- 이름이 없기 때문에 생성자도 가질 수 없으며, 조상클래스의 이름이나 구현하고자 하는 인터페이스의 이름을 사용해서 정의하기 때문에 오로지 단 하나의 클래스를 상속받거나 단 하나의 인터페이스만을 구현할 수 있다.
- 익명 클래스는 이름이 없기 때문에 ‘외부 클래스명$숫자.class’의 형식으로 클래스파일명이 결정