728x90
1. InnerClass
- innerclass 란 이너 클래스로 불리는 하나의 클래스로, 클래스나 인터페이스 내부에 선언되는 클래스이다.
- 쉽게 이야기하면 클래스 안에 선언된 클래스로, 코드를 보다 읽기 쉽고, 재사용 가능하도록 하는 장점이 있다.
- 바깥쪽에 선언된 outer class 와 안쪽에 선언된 innerClass 는 서로 밀접한 관련이 있다.
1) 기본 innerClass
- 기본 innerClass 말 그대로 가장 기본적인 innerClass 이다.
- 아주 단순하게 클래스 안에 클래스를 선언하는 방법으로 사용한다.
- InnerClass 의 인스턴스를 생성할때는 다음과 같이 사용한다.
- innerClass 는 outer 클래스의 안쪽에 존재하기 때문에 당연히 outerClass 에서 선언된 모든 변수와 메서드를 사용할 수 있다.
public class InnerClass {
int a = 10;
static int b = 20;
private int c = 30;
private static int d = 40;
class num {
void print() {
System.out.println("a : "+a);
System.out.println("b : "+b);
System.out.println("c : "+c);
System.out.println("d : "+d);
}
void innerMethod() {
outerMethod();
}
}
void outerMethod() {
System.out.println("나는 outerClass의 메서드");
}
public static void main(String[] args) {
// 1. outerClass 인스턴스 생성
InnerClass ic = new InnerClass();
// 2. innerClass 인스턴스 생성 =>
// outerClass.innerClass 참조변수명 = outClass의 인스턴스.new innerClass생성자
InnerClass.num icn = ic.new num();
icn.print();
/*
* ## 결과 ##
* a : 10
* b : 20
* c : 30
* d : 40
*/
icn.innerMethod();
/*
* ## 결과 ##
* 나는 outerClass의 메서드
*/
}
}
2) static InnerClass
static 으로 선언된 innerClass 는 복잡한 인스턴스 생성과정없이 바로! 인스턴스 생성이 가능하다 -> static 이니까!!
다만 innerClass 를 static 으로 선언하는 경우 다음과 같은 주의점이 있다.
- innerClass 는 static 이지만 outerClass 에서 선언된 필드 - 멤버 - 변수나 method 가 static 이 아닌 경우 static 으로 선언된 InnerClass 에서는 사용할 수 없다.
- 이는 사실 당연한 것인데, innerClass 의 경우 static 으로 설정되면 static area 에 올라가서 바로 사용이 가능하지만 outerClass 에 선언된 멤버 변수나 메서드의 경우 static 이 붙지 않았다면 먼저 인스턴스를 생성해서 메모리에 올려주어야하기 때문에 그 전에는 사용할 수 없게 된다.
- 이 때문에 아직 인스턴스가 생성되지 않은 InnerClass 의 안에서는 해당 변수나 메서드를 사용할 수 없는 것이다.
- 물론 static 으로 설정된 필드 변수와 메서드의 경우 InnerClass 에서도 사용할 수 있다.
public class OuterClass {
int a = 10;
static int b = 20;
private int c = 30;
private static int d = 40;
static class StaticInnerClass{
// 안쪽 클래스가 static 인 경우 outerClass 의 static 변수, static 메서드만 사용가능하다
// 이는 outerClass 의 인스턴스가 아직 생성 전이기 때문에...!!
void print() {
// System.out.println("a : "+a); 에러 발생
System.out.println("b : "+b);
// System.out.println("c : "+c); 에러 발생
System.out.println("d : "+d);
}
void innerMethod() {
System.out.println("나는 static InnerClass 메서드");
// outerMethod();
staticOuterMethod();
}
}
void outerMethod() { // 에러 발생
System.out.println("나는 outerClass의 메서드");
}
static void staticOuterMethod() {
System.out.println("나는 outerClass의 static 메서드");
}
public static void main(String[] args) {
StaticInnerClass sic = new StaticInnerClass();
sic.print();
sic.innerMethod();
}
}
3) Local Inner Class
- local innerClass 는 메서드 안에서 선언된 클래스이다.
- 메서드 안에서 선언되고 사용되기 때문에 일종의 메서드 안에서만 사용되는 지역변수와 비슷하다고 생각할 수 있다.
- 따라서 메서드가 종료되면 해당 클래스와 관련된 내용들도 같이 종료된다.
- 보통 OuterClass 에서 메서드를 하나 선언 후 그 메서드 내부에서 클래스를 선언하고, 인스턴스를 만들어서 해당 innerClass 의 메서드를 실행하는 코드를 넣어준다. 이후 외부에서는 outerClass 의 인스턴스를 생성 후 메서드를 실행하여 innerClass 의 내용을 실행하는 방법을 사용한다 => 외부에서는 사실상 접근 불가능하다
public class OuterClass2 {
static final int b = 40;
void inner() {
class LocalInnerClass{
// static 으로 선언된 변수도 메서드 밖에서는 사용 불가 =>
//LocalInnerClass 의 변수는 메서드 안에서 선언되는 지역변수처럼 취급되기에
// 메서드가 종료되면 관련 내용도 같이 없어지기 때문
int a = 10;
static final int b = 30;
void print() {
System.out.println("a : "+a);
System.out.println("b : "+b);
}
}
// 이렇게 LocalInnerClass 의 인스턴스 생성이 없다면 외부에서는 접근 불가...!!
LocalInnerClass lic = new LocalInnerClass();
lic.print(); // a 와 b 값 출력
}
void change() {
// 여기서 불러오는 b 는 outerClass 에서 선언된 b 의 값 = 40
System.out.println(b);
}
public static void main(String[] args) {
OuterClass2 oc = new OuterClass2();
oc.change(); // 40
oc.inner(); // a 와 b 값 출력 =>
// 참조변수 oc로 inner() 메서드 접근 -> inner() 메서드 안에 선언된 lic.print() 실행
// oc.inner().lic.print(); 이런거는 불가능!!
}
}
4) 익명 innerClass
- 익명 innerClass 는 익명 클래스라고도 불리며, 생성자 안에 클래스를 껴 넣는 것을 말한다.
- 클래스의 선언과 객체의 생성을 동시에!! 하는 이름없는 클래스로 일회용 클래스로서 사용된다.
- 생성자 매개변수에 클래스를 끼워넣음으로써 본래 매개변수로 와야하는 클래스의 생성자로서 동작한다.
- 만약 본래 와야하는 매개변수가 인터페이스나 추상 클래스의 구현 클래스라면 이렇게 익명 클래스를 만들어서 끼워넣는 식으로 해당 인터페이스나 추상 클래스를 상속, 구현한 클래스로서 취급한다.
- 대표적으로 아래의 자바의 Frame 에서 이벤트와 관련해서 사용하는 예시에서 찾아볼 수 있다.
- addWindowListener 의 생성자의 매개변수로는 WindowListener 인터페이스를 구현한 구현 클래스 혹은 추상 클래스인 WindowAdapter 를 상속받아 구현한 클래스가 와야한다.
- 하지만 매번 이렇게 상속받아서 사용하거나 구현하기 힘들기 때문에 보다 간결하게 코드를 짜기위해 익명클래스가 사용된다.
- 즉 addWindowListener 의 생성자 매개변수로 new WindowAdapter() 를 구현한 클래스 생성자가 오는데 이때 익명클래스를 사용한다. 익명클래스로 선언되는 { ~~~} 안쪽은 암시적으로 WindowAdapter를 상속받아 구현한 클래스가 되는 것이다.
MyWin(){
this.setVisible(true);
this.setBounds(200, 200, 800, 600);
this.addWindowListener(new WindowAdapter()
(여기서부터 클래스가 된다 => 이름없는 익명 클래스){
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
2. 제네릭 자료형
- 제네릭 자료형은 클래스 내부에서 사용될 자료형을 본인이 지정하는 것이다.
- 쉽게 이야기해서 클래스 내부에서 사용될 자료형을 임시 상태로 두고, 클래스 인스턴스를 만든 후 사용할 때마다 내가 원하는 자료형을 넣어서 클래스를 사용하게 되는 것이다.
- 모든 자료형에 대해서 처리가 가능하며, 아직 자료형ㅇ르 결정하지 않은 미완성 자료형으로 선언된다.
- 이 자료형 안에는 클래스도 올 수 있다.
- 선언은 [클래스명]<타입명> 으로 한다. 대표적으로 아래처럼 사용한다.
- Generic<T> : 이때 T 는 Type 을 의미하며 제네릭형으로 사용한다는 암시적 표현정도? 사실 뭐가 와도 상관없단다
- 제네릭 타입의 가장 큰 장점은 자료형을 미리 결정하지 않는 다는 점!! 즉 인스턴스 생성해서 사용할 때 자료형을 결정하고 사용하기 때문에 코드 재사용과 편의성이 높아진다.
- 제네릭 타입의 대표적인 것은 ArrayList. ArrayList 안에는 Integer, String 혹은 어떤 클래스의 인스턴스가 올 수 도 있다. 이 모든것은 ArrayList 가 제네릭이기 때문에 가능하다!!
- 아래 예시처럼 내가 Integer 타입일 때, String 타입일 때 등 내가 원할 때 마다 바꿔서 해당 클래스를 사용할 수 있다.
// 제네릭 클래스 선언
public class Generic<T> {
T[] array; // T 라는 타입으로 선언된 array
public void setArray(T[] array) {
this.array = array; // array 초기화
}
T[] getArray() {
return array; // array 반환
}
void print(T[] array) {
for(T a : array) {
System.out.print(a+" ");
}
System.out.println();
}
public static void main(String[] args) {
// 1. Integer 타입을 선언
Generic<Integer> gi_int = new Generic<Integer>();
Integer[] intArr = { 10, 20, 30, 40, 50};
gi_int.setArray(intArr);
System.out.println(gi_int.getArray()); // [Ljava.lang.Integer;@27808f31
gi_int.print(intArr); // 10 20 30 40 50
System.out.println("--------------------------------");
// 2. STring 타입을 선언
Generic<String> gi_str = new Generic<String>();
String[] strArr = {"저그","테란","프로토스","스타"};
gi_str.setArray(strArr);
System.out.println(gi_str.getArray()); // [Ljava.lang.String;@436e852b
gi_str.print(strArr); // 저그 테란 프로토스 스타
}
}
- 참고
JAVA - 익명클래스(Anonymous class)란?
https://preamtree.tistory.com/138
'Java - 기본기' 카테고리의 다른 글
25. Java Swing 과 JFrame, Graphics (0) | 2022.04.05 |
---|---|
24. Thread - 스레드 다루기(feat. Lotte 번호찍기) (0) | 2022.03.14 |
22. 추상 클래스, 인터페이스, static, final (0) | 2022.03.05 |
클래스, 메서드, 생성자, 상속 정리 : 나만의 StarCraft (0) | 2022.03.01 |
21. 접근제어자와 상속, 오버라이드 (0) | 2022.03.01 |
댓글