반응형
내부클래스:
클래스 내부에 선언한 클래스로
클래스 내부에서만 사용할 목적으로 만드는 클래스이다.
//문법
class Out{ //외부클래스
class In{ //내부클래스
}
}
내부클래스의 종류
[변수 측면에서]
class ABC{
int n1; //인스턴스 변수
static int n2; //정적변수
public void abc(){
int n3; //지역변수
}
}
[클래스 측면에서]
class ABC{//외부클래스
class In{//인스턴스 내부클래스 - static이 붙지않음
static class SIn{//정적 내부 클래스 - static이 붙음
}
}
public void abc(){//메소드 안에도 클래스가 들어갈 수 있다.
class Local{//지역 내부 클래스
}
}
}
//최상위만 외부, 나머진 모두 내부
인스턴스 내부 클래스 (instance inner class)
- 외부 클래스를 생성한 후 생성
- 정적 변수, 정적 메서드는 사용할 수 없다.
- 외부 클래스의 참조 변수를 이용하여 내부 클래스를 사용한다.
- 내부 클래스가 private이 아니면 다른 외부 클래스에서도 생성가능하다.
- 클래스 내부에서만 사용할 목적이라면 private로 선언한다.
[실습] 인스턴스 내부 클래스 실행하기
//외부 클래스 정의
class OutClass{
//필드 정의
private int num = 10; //외부 클래스 인스턴스 변수
private static int sNum = 20; //외부 클래스 정적 변수
//내부 클래스 자료형 변수를 먼저 선언
private InClass inClass;
//외부클래스의 디폴트 생성자 정의
//외부 클래스가 생성된 후에 내부 클래스 생성가능
public OutClass() {
inClass = new InClass();
}
//인스턴스 내부 클래스 정의
class InClass{
int inNum = 100; //내부 클래스의 인스턴스 변수
//인스턴스 내부 클래스에 정적 변수 선언은 불가능->오류발생
//static int SInNum = 200;
//메서드 정의
void inTest() {
System.out.println(num); //외부 클래스의 인스턴스 변수
System.out.println(sNum); //외부 클래스의 정적 변수
}
//인스턴스 내부 클래스에서 정적 메소드 정의 불가능 ->오류 발생
//static void sTest() {}
}
//다른 메서드를 선언하는 메서드 정의
public void usingClass() {
inClass.inTest();
}
}
public class InnerClassTest {
public static void main(String[] args) {
//OutClass 객체 선언
OutClass outClass = new OutClass();
//내부 클래스의 메소드 호출
outClass.usingClass();//20 10출력
}
}
정적 내부 클래스(static inner class)
- 외부 클래스의 생성과 무관하게 사용가능
- 정적 변수, 정적 메서드 사용가능
[정적 내부 클래스의 메서드에서 변수 사용 여부]
정적 내부 클래스의 메서드 | 변수의 유형 | 사용가능 여부 |
일반 메서드 void inTest() |
외부 클래스의 인스턴스 변수(num) | X |
외부 클래스의 정적 변수(sNum) | O | |
정적 내부 클래스의 인스턴스 변수(inNum) | O | |
정적 내부 클래스의 정적 변수(sInNum) | O | |
정적 메서드 static void sTest() |
외부 클래스의 인스턴스 변수(num) | X |
외부 클래스의 정적 변수(sNum) | O | |
정적 내부 클래스의 인스턴스 변수(inNum) | X | |
정적 내부 클래스의 정적 변수(inNum) | O |
[실습] 정적 내부 클래스 실행
//외부클래스
class OutClass{
//필드정의
private int num = 10; //외부 클래스 인스턴스 변수
private static int sNum = 20; //외부 클래스 정적 변수
//정적 내부 클래스를 정의
static class InStaticClass{
int inNum = 100; //정적 내부 클래스의 인스턴스 변수
static int sInNum = 200; //정적 내부 클래스의 정적 변수
//정적 내부 클래스의 일반 메서드 정의
void inTest() {
//System.out.println(num); //외부 클래스 인스턴스 변수
System.out.println(sNum); //외부 클래스 정적 변수
System.out.println(inNum); //정적 내부 클래스의 인스턴스 변수
System.out.println(sInNum); //정적 내부 클래스의 정적 변수
}
//정적 내부 클래스의 정적 메서드 정의
static void sTest() {
//System.out.println(num); //외부 클래스 인스턴스 변수
System.out.println(sNum); //외부 클래스 정적 변수
//System.out.println(inNum);//정적 내부 클래스의 인스턴스 변수
System.out.println(sInNum); //정적 내부 클래스의 정적 변수
}
}
}
public class StaticInnerClassTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//외부 클래스 객체를 생성하지 않고 바로 정적 내부 클래스 객체 생성이 가능.
OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
sInClass.inTest();//일반메서드
System.out.println("===============");
OutClass.InStaticClass.sTest();//정적메서드
}
}
지역 내부 클래스(Local Inner Class)
- 지역 변수와 같이 메서드 내부에서 정의하여 사용하는 클래스
- 메서드의 호출이 끝나면 메서드의 사용된 지역 변수의 유효성은 사라진다.
- 메서드 호출 이후에서 사용해야 하는 경우가 있으므로 지역 내부 클래스에서 사용하는 메서드의 지역변수나 매개 변수는 final로 선언
[실습] 지역 내부 클래스 실행
//외부클래스
class OutClass{
//필드 선언 및 초기화
int outNum = 100; //외부클래스 인스턴스 변수
static int sNum = 200; //외부클래스 정적 변수
//Runnable 인터페이스를 구현하기 위한 메서드 정의
Runnable getRunnable(int i) {
int num = 100; //지역변수
//지역 내부 클래스를 정의
class MyRunnable implements Runnable{
int localNum = 10; //지역 내부 클래스의 인스턴스 변수
@Override
public void run() {
// TODO Auto-generated method stub
//num = 200;//final을 쓰진 않았지만 final을 쓴 것과 같은효과
//i=100; //매개변수도 지역변수이기 때문에 같은 오류 발생
System.out.println(i);
System.out.println(num); //지역변수
System.out.println(localNum); //지역 내부 클래스의 인스턴스 변수
System.out.println(outNum); //외부클래스 인스턴스 변수
System.out.println(sNum); //외부클래스 정적 변수
}
}
return new MyRunnable();
}
}
public class LocalInnerClassTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//객체생성
OutClass outClass = new OutClass();
//메서드를 호출하여 결과값을 runner에 대입
Runnable runner = outClass.getRunnable(10);
runner.run();
}
}
익명 내부 클래스(Anonymous Inner Class)
이름이 없는 클래스
주로 하나의 인터페이스나 하나의 추상 클래스를 구현하는데 더 사용
인터페이스나 추상 클래스 자료형의 변수에 직접 대입하여 생성하거나 지역 내부 클래스의 메서드 내부에서 생성하여 반환 할 수 있다.
*참고- 안드로이드의 widget의 이벤트 핸들러를 구현할 때 많이 사용
[실습]익명 내부 클래스 실행
//외부클래스
class OutClass{
//메소드 정의
Runnable getRunnable(int i) {
int num = 100; //지역변수
//MyRunnable 클래스 이름을 빼고 클래스를 바로 생성
return new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(i);//출력은 되나 변경은 불가능
System.out.println(num);//출력은 되나 변경은 불가능
}}; //클래스 끝에 세미콜론(;)을 넣어준다
}
//익명 내부 클래스를 변수에 대입 가능
Runnable runner =new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("익명 클래스");
}
};
}
public class AnonymousInnerClassTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
OutClass outClass = new OutClass();
//메서드를 호출하여 결과값을 runner에 대입.
Runnable runner = outClass.getRunnable(10);
//메서드 호출
runner.run();
outClass.runner.run();
}
}
[정리]
인스턴스 내부 클래스 | 정적 내부 클래스 | 지역 내부 클래스 | 익명 내부 클래스 | |
구현위치 | 외부 클래스 멤버 변수와 동일 | 외부 클래스 멤버 변수와 동일 | 메서드 내부에 구현 | 메서드 내부에 구현 변수에 대입하여 직접 구현 |
사용할 수 있는 외부 클래스 변수 | 외부 인스턴스 변수, 외부 전역변수 | 외부 전역변수 | 외부 인스턴스 변수, 외부 전역변수 | 외부 인스턴스 변수, 외부 전역 변수 |
생성방법 | 외부 클래스를 먼저 만든 후 내부 클래스 생성 | 외부 클래스와 무관하게 생성 | 메서드 호출할 때 생성 | 메서드를 호출할 때 생성되거나, 인터페이스 타입변수에 대입할 때 new 예약어를 사용하여 생성 |
반응형
'Language > JAVA' 카테고리의 다른 글
[JAVA]Class 클래스 (0) | 2020.07.01 |
---|---|
[JAVA] 람다식(lambda expression) (0) | 2020.07.01 |
[JAVA]StringBuffer VS StirngBuilder (0) | 2020.07.01 |
[JAVA]String 클래스 (0) | 2020.07.01 |
[JAVA]Object 클래스 (0) | 2020.07.01 |
댓글