내부 클래스 Inner Class
class A{
class B{
}
}
위와 같이 클래스 내부에 또 다른 클래스가 존재할 수 있다.
B는 A의 내부 클래스이고, A는 B의 외부 클래스이다.
내부 클래스 B는 외부 클래스인 A가 아닌 클래스에서 잘 사용되지 않아야 한다.
외부 클래스가 아닌 다른 클래스에서 내부 클래스에 접근해야 한다면 내부 클래스로 선언해서는 안 되는 클래스를 내부 클래스로 선언했다는 의미이기 때문이다.
보통 AWT, Swing 등의 GUI 이벤트 처리 외에는 잘 사용되지 않는다.
내부 클래스의 장점
- 내부 클래스에서 외부 클래스의 멤버들에게 쉽게 접근이 가능하다.
- 코드의 복잡성을 줄여준다. (캡슐화)
- 외부에는 불필요한 클래스를 감출 수 있기 때문이다.
내부 클래스의 종류와 특징
class Outer{ //외부 클래스
class InstanceInner{ } //인스턴스 클래스
static class StaticInner{ } //스태틱 클래스
void method(){
class LocalInner{ } //지역 클래스
}
}
- 스태틱 클래스 : 외부 클래스의 멤버 변수 선언 위치에 선언
- 외부 클래스의 static 멤버처럼 다뤄진다.
내부 클래스에 static 변수를 선언해야 한다면 스태틱 클래스로 선언해야 한다.
(단, staic final이 동시에 붙은 상수는 모든 내부 클래스에서 정의할 수 있다.) - 주로 외부 클래스의 static멤버, 특히 static메소드에서 사용될 목적으로 선언
- 스태틱 클래스는 네스티드 클래스이지만, 내부 클래스(이너 클래스)로는 분류되지 않기도 한다.
(이 경우 멤버, 로컬, 익명 클래스만 네스티드 클래스이면서 이너 클래스)
- 외부 클래스의 static 멤버처럼 다뤄진다.
- 멤버 클래스 : 외부 클래스의 멤버 변수 선언 위치에 선언
- =인스턴스 클래스
- 외부 클래스의 인스턴스 멤버처럼 사용
- 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에서 사용
- 지역 클래스 : 외부 클래스의 메소드나 초기화 블럭 안에서 선언.
- 선언된 영역 내부에서만 사용
- 익명 클래스 : 클래스 선언과 객체의 생성을 동시에 하는 이름 없는 클래스(일회용)
package innerClass;
//멤버 클래스
/* 멤버 클래스와 static클래스는 외부 클래스의 멤버 변수와 같은
* 위치에 선언됩니다. 또한 멤버 변수와 같은 성질을 가집니다.
*
* 다른 책에서는 멤버 변수를 이렇게 말하고 있습니다.
* 정적 클래스 static이 아닌 경우 (static선언이 없으면)
* 내부 클래스라고 부릅니다.
*
* 내부 클래스는 클래스 내에 선언되므로 인스턴스 속성 변수처럼
* 활용됩니다.
* 즉 메소드 {} 안에서만 유효합니다.
*
* 인스턴스 변수는 클래스 내에서 선언되지만 메소드 밖에서,
* 생성자 밖에서, 다른 블록 밖에서 선언됩니다.
* (이경우 반드시 초기화가 필요합니다)
*
* 내부 클래스는 외부 클래스의 멤버를 활용할 수 있지만
* 외부 클래스는 내부 클래스의 멤버 변수를 활용할 수 없습니다.
* 또한 static이 붙은 메소드 내에서는 내부 클래스의 객체 선언X
*
*/
public class MemberClass01 {
private int outerDf = 10;
private static int osi = 55;
int number = 777;
void outerMethod() {
System.out.println(number);
System.out.println(osi);
System.out.println(this.osi);
}
static void outterSM() {
System.out.println(osi);
//System.out.println(number);//X
}
public class InnerClass{
private int x = 100;
int innerDf = 100;
static final int ISI = 123;
public void innerMethod() {
int imnum = osi;//외부 클래스 private static int osi = 55;
System.out.println(x);
System.out.println(innerDf);
System.out.println(ISI);
System.out.println(number);
System.out.println(outerDf);
}
}
public static void main(String[] args) {
MemberClass01 memberClass01 = new MemberClass01();
//MemberClass01.InnerClass in = new MemberClass01.InnerClass();
MemberClass01.InnerClass in = memberClass01.new InnerClass();
in.innerMethod();
//내부 클래스 -> 입출력 -> 쓰레드 -> 네트워킹 -> 그래픽
}
}
package innerClass;
//static class
/* class앞에 static이 붙은 것이 차이점
* static이 붙었기 때문에 객체 생성없이 사용가능합니다.
* 클래스의 static 변수처럼 사용됩니다.
* 외부 클래스와 내부 클래스는 다르게 동작합니다.
* 외부 클래스와 내부 클래스의 멤버가 private라도 상호 접근 가능
* 경로만 지정된다면 단독으로 직접 사용할 수 있습니다.
*
* 책 390
*/
public class StaticClass01 {
private int num = 1;//객체 생성, 외부X
int sc = num;//객체 생성. 외부O
private static int outterSI = 0;//클래스명. 객체X, 외부X
public static void outterMethod() {
System.out.println(SInner.innerSM);
}
public static class SInner{
private int innerMember = 200;
private static int innerSM = 300;
final int LV = 100;
public static void innerMethod() {
System.out.println("static 클래스 내부 static 메소드");
}
public void innerM() {
System.out.println("static 클래스 내부 클래스");
System.out.println("this.innerSM " + this.innerSM);
//System.out.println("sc " + sc); 호출 불가
System.out.println("outterSI" + outterSI);
}
}
public static void main(String[] args) {
StaticClass01 staticClass01 = new StaticClass01();
StaticClass01.SInner si = new SInner();
StaticClass01.SInner si2 = new StaticClass01.SInner();
si.innerMethod();
si.innerM();
//si.innerMember;
//si.LV;
StaticClass01.SInner.innerMethod();
//StaticClass01.SInner.innerM();객체 생성 후 호출
//aaa객체 생성
AAA aaa = new AAA();
//System.out.println(aaa.BBB..);//불가 -> 얘가 안보이고
//System.out.println(AAA.BBB.);//안보임 -> 얘가 오류뜨는데?
AAA.BBB bbb = new AAA.BBB();
System.out.println(bbb.number2);
//bbb.number = 20;//The field AAA.BBB.number is not visible?
//BBB.number = 20;//BBB cannot be resolved to a variable?
}
}
//private: 같은 클래스에서만 접근 가능
//내부 클래스 - 외부 클래스 서로 접근 가능
class AAA{
private static int innerNum = BBB.number;//내부 클래스의 pirvate 접근 가능
private static int outternum = 100;
static class BBB{
private static int number = 10;
int number2 = outternum;//외부 클래스의 private도 접근 가능
}
}
package innerClass;
//지역클래스
/* Local Class
* 메소드 안에 선언한 클래스
* 선언한 메소드 내에서만 사용하기 위해서 내부에 선언합니다.
* 메소드 안에서만 지역변수처럼 클래스를 활용하므로
* 메소드의 실행이 끝나면 지역 클래스는 제거됩니다.
*
* 외부에서 인스턴스를 생성할 수 없습니다.
* 또한 static을 사용할 수 없습니다.
* instance변수 또는 메소드는 사용할 수 있습니다.
*
* final붙은 지역변수(상수처리)하거나 매개변수는
* 지역 클래스의 메소드에서 접근 가능합니다.
*
* 객체를 생성해서 활용해야 합니다.
* 컴파일 하면 외부 클래스$숫자+로컬 클래스명.class로 만들어집니다
* 숫자는 서로 다른 메소드인 경우 같은 이름의 클래스가
* 존재할 수 있어서 구분하기 위해서 붙입니다.
*
*
*/
public class LocalClass01 {
private int a = 10;
final int LV = 100;
void method() {
int in = 100;
final int inD = 1000;
class LocalClass{
int no = 99;
void msg() {
no = no + 10;
System.out.println("외부 a " + a);
System.out.println(LocalClass01.this.a);
System.out.println(in);
System.out.println(inD);
}
}//LocalCalass 끝
//지역 클래스가 선언된 메소드 안에서 객체를 만듭니다.
LocalClass local = new LocalClass();
local.msg();//객체 생성 후에 호출해서 사용합니다.
}//메소드 끝
public static void main(String[] args) {
LocalClass01 localClass01 = new LocalClass01();
localClass01.method();
}
}
package innerClass;
import java.util.ArrayList;
import java.util.List;
//익명 클래스
/* Anonymous Class
*
* 클래스 명 없는 클래스
* 선언과 동시에 인스턴스 생성을 하나로 통합한 클래스
* 클래스를 인수의 값으로 활용하는 클래스
*
* 객체를 한번만 사용할 경우 사용합니다.
* 클래스의 선언부가 없기 때문에 이름이 없으므로
* 생성자를 가질 수 없습니다.
* 슈퍼 클래스의 이름이나 구현할 인터페이스를 구현하거나
* 둘 이상의 인터페이스를 구현할 수 없습니다.
* 오직 하나의 클래스를 상속받거나 하나의 인스턴스만 구현 가능합니다.
*
* 코드 블럭에 클래스 선언을 하는 점만 빼고는
* 생성자를 호출하는 것과동일합니다.
*
* 객체를 구성하는 new문장 뒤에 클래스의 블럭{}을 첨부하여
* 몸통을 닫는 형식으로 구성됩니다.
*
* new 슈퍼 클래스 또는 인터페이스명(){};
*
* 객체를 생성한 후에 {}; 즉 메소드를 구현한 블록이 있고
* 블록 끝에는 세미콜론이 붙습니다.
*
*
* new 뒤에 오는 생성자명이 기존 클래스명이면 익명클래스가
* 자동으로 클래스의 하위 클래스가 됩니다.
*
* 인터페이스인 경우에는 인터페이스를 상속하는 부모 클래스가
* Object가 됩니다.
*
*
*/
interface Sound{
abstract void sound();//불완전 요소
}
abstract class Animal{
String name;
int age;
}
class Cat extends Animal implements Sound{
@Override
public void sound() {
}
}
class Dog{
}
class Mouse{
}
class AMClass{
public void method() {
System.out.println("method");
}
}
public class Anonymous {
public static void main(String[] args) {
//상속 -> 추상화 -> 인터페이스 -> 다형성
//List<String> list = new List<String>();
//이렇게 만들 수 없어요. = 미구현된 메소드 완벽하지 X
//인터페이스는 상속받는 자식 클래스로 생성해요.
AMClass amc = new AMClass() {
@Override
public void method() {
System.out.println("오버라이드 했습니다.");
}
};
amc.method();
}
}
참고하면 좋은 글
https://siyoon210.tistory.com/141
https://pridiot.tistory.com/52
'BackEnd > Java' 카테고리의 다른 글
[Java] 아파치 POI 설치 및 사용법 (0) | 2021.07.26 |
---|---|
[Java] IO Stream (0) | 2021.07.26 |
[Java] 예외 Exception (0) | 2021.07.19 |
[Java] 2진트리 Binary Tree (0) | 2021.07.19 |
[Java] 스택(Stack), 큐(Queue) (0) | 2021.07.19 |
댓글