OOP(4) : 내부 클래스
갈수록 정리하는 데 시간이 오래 걸리는군...
객체 지향 프로그래밍(OOP: Object-Oriented Programming)
1. 데이터 보호
패키지 / 접근제어자 / 캡슐화
2. 재사용
변경해서 사용(상속 : is-a) / 그대로 사용(포함 : has-a)
3. 다형성
오버라이딩 / 오버로딩
4. 형변환
5. 추상 클래스 / 인터페이스
+5 내부 클래스 ← 오늘은 여기!
6. 예외처리
내부 클래스
아래와 같이 클래스 내에 선언되는 클래스이다. 대신 객체 생성이 번거로워짐.
class A { //외부 클래스
...
class b{ //내부 클래스
...
}
}
두 클래스가 서로 관계가 있을 때 서로 쉽게 접근할 수 있도록 하고, 외부에는 불필요한 클래스를 감추는 데 이용한다.
static클래스만 static 멤버를 정의할 수 있다.
⇢ 단, final static은 상수이므로 모든 내부 클래스에서 허용된다.
변수처럼 선언 위치에 따라 내부 클래스의 종류가 나눠진다.
내부 클래스의 종류와 특징 | |
인스턴스 클래스 (instance class) |
외부 클래스의 멤버 변수 선언 위치에 선언 / 외부 클래스의 인스턴스멤버처럼 쓰임 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 이용 |
스태틱 클래스 (static class) |
외부 클래스의 멤버 변수 선언 위치에 static으로 선언 / 외부 클래스의 static 멤버처럼 쓰임 주로 외부 클래스의 static멤버, 특히 static 메서드에서 사용 |
지역 클래스 (local class) |
외부 클래스의 메서드나 초기화 블록 안에 선언 / 선언된 영역 내에서만 사용 |
익명 클래스 (anonymous class) |
클래스의 선언과 객체의 생성을 동시에 하는 이름 없는 클래스(1회용) |
인스턴스 클래스(멤버 클래스)
외부 클래스와 스태틱 클래스의 인스턴스 멤버를 객체 생성 없이 바로 사용할 수 있다.
Outer1과 Inner1이 서로 변수와 메서드를 자유롭게 사용할 수 있다.
private 멤버도 접근이 가능하다! ↓ 외부 클래스의 private String name에 접근한 걸 볼 수 있음.
class Outer1 {
private String name = "kimdoodoo";
class Inner1 {
int a = 10;
public void print() {
System.out.println("Inner:print() Call..:name=" + name);
}
}
}
public class Ex1 {
public static void main(String[] args) {
Outer1 o1 = new Outer1();
Outer1.Inner1 i1 = o1.new Inner1();
System.out.println(i1.a); //10
i1.print(); //Inner:print() Call..name=kimdoodoo
}
}
class Outer{
int value = 10;
public void display() {
Inner i = new Inner();
i.method();
}
//Inner 클래스는 Outer의 메서드를 제어
class Inner{
int value = 20;
public void method() {
int value = 30;
System.out.println("value="+value);
//지역변수 우선순위=>30
System.out.println("this.value="+this.value); //20
System.out.println("Outer.value="+Outer.this.value);//10
}
}
}
public class Ex3 {
public static void main(String[] args) {
Outer o = new Outer();
Outer.Inner i = o.new Inner();
i.method();
}
}
스테틱 클래스(멤버 클래스)
외부 클래스와 인스턴스 클래스의 인스턴스 멤버를 객체 생성 없이 사용할 수 없다.
인스턴스 클래스와 달리 Outer2의 생성자 사용 없이 내부 클래스의 객체를 생성할 수 있음.
*Outer1.Inner1 i1 = new Outer1.Inner1() < 에러 난다.
class Outer2 {
static class Inner2 {
public void print() {
System.out.println("Inner:print() Call..");
}
}
}
public class Ex1 {
public static void main(String[] args) {
Outer2.Inner2 i2 = new Outer2.Inner2();
i2.print();//Inner:print() Call..
}
}
지역 클래스
외부 클래스의 메서드나 초기화 블록 안에 선언하여 선언된 영역 내에서만 사용 가능하다.
지역 클래스는 외부 클래스의 인스턴스 멤버와 static 멤버를 모두 사용할 수 있다.
+ 지역 클래스가 포함된 메서드에 정의된 지역 변수도 final에 한해 사용 가능하다.
→ 메서드가 수행을 마치고 지역 변수가 소멸된 시점에도 지역 클래스의 인스턴스가
소멸된 지역 변수를 참조하려는 경우가 발생할 수 있기 때문이다.
class Outer3 {
public void print() {
class Inner3 {
public void print() {
System.out.println("지역 클래스:Inner:print() Call..");
}
}
Inner3 i = new Inner3();
i.print();
}
}
public class Ex1 {
public static void main(String[] args) {
Outer3 o3 = new Outer3();
o3.print(); //지역 클래스:Inner:print() Call..
}
}
익명 클래스
클래스의 선언과 객체의 생성을 동시에 해서 이름이 없다.
딱 한 번만 사용될 수 있고, 하나의 객체만을 생성할 수 있는 1회용 클래스.
이름이 없다 = 생성자를 가질 수 없다.
class Outer4 {
Inner4 in = new Inner4() { //익명 클래스
public void print() {
System.out.println("Outer4:print() Overrriding..");
}
};
}
class Inner4 {
public void print() {
System.out.println("Inner4:print() Call..");
}
}
public class Ex1 {
public static void main(String[] args) {
Inner4 i4 = new Inner4();
i4.print(); //Inner4:print() Call..
Outer4 o4 = new Outer4();
o4.in.print(); //Outer4:print() Overrriding..
}
}
실습예제
Server.class
package day24.server;
import java.net.*;
import java.util.*;
import java.io.*;
public class Server implements Runnable {
private ServerSocket ss;
private final int PORT = 3355;
private Vector < Client > waitVc = new Vector < Client > ();
//Server (접속 담당)
public Server() {
try {
ss = new ServerSocket(PORT);
System.out.println("Server Start...");
} catch (Exception ex) {}
}
@Override
public void run() {
while (true) {
try {
Socket s = ss.accept();
//클라이언트가 접속하면 아이피를 받아오는 메서드
Client client = new Client(s);
System.out.println(s.getPort());
System.out.println(s.getInetAddress().getHostAddress());
waitVc.add(client);
client.start();
} catch (Exception ex) {}
}
}
public static void main(String[] args) {
Server server = new Server();
new Thread(server).start();
// s.run();
}
//Client (통신 담당) 내부 클래스!
class Client extends Thread {
Socket s;
OutputStream out;
BufferedReader in ;
public Client(Socket s) {
try {
this.s = s;
out = s.getOutputStream(); in = new BufferedReader(
new InputStreamReader(s.getInputStream()));
} catch (Exception ex) {}
}
public void run() {
while (true) {
try {
String msg = in .readLine();
for (Client c: waitVc) {
//인스턴스 내부클래스
c.out.write((msg + "\n").getBytes());
}
} catch (Exception ex) {}
}
}
}
}
Client.class
package day24.client;
import java.util.*;
import java.net.*;
public class Client {
public static void main(String[] args) {
try {
Socket s = new Socket("localhost",3355);
}catch(Exception ex) {}
}
}
'부트캠프(END) > Java' 카테고리의 다른 글
OOP(5) : 예외 처리 / try-catch, throw, finally (0) | 2022.06.07 |
---|---|
OOP(3) : 형변환, 추상 클래스, 인터페이스 (0) | 2022.06.02 |
OOP(2) : 재사용, 다형성 (0) | 2022.05.31 |