Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- @Aspect
- 스프링 mvc2 - 타임리프
- 스프링 mvc2 - 검증
- 스프링 mvc1 - 스프링 mvc
- 타임리프 - 기본기능
- 자바의 정석 기초편 ch14
- 스프링 db1 - 스프링과 문제 해결
- 자바의 정석 기초편 ch2
- 스프링 mvc2 - 로그인 처리
- 자바의 정석 기초편 ch6
- 자바의 정석 기초편 ch11
- 2024 정보처리기사 수제비 실기
- 자바의 정석 기초편 ch1
- 자바의 정석 기초편 ch7
- 게시글 목록 api
- 자바의 정석 기초편 ch9
- 스프링 mvc1 - 서블릿
- 자바의 정석 기초편 ch12
- 스프링 고급 - 스프링 aop
- 코드로 시작하는 자바 첫걸음
- 자바의 정석 기초편 ch13
- 스프링 입문(무료)
- jpa 활용2 - api 개발 고급
- 2024 정보처리기사 시나공 필기
- 자바의 정석 기초편 ch5
- jpa - 객체지향 쿼리 언어
- 자바의 정석 기초편 ch4
- 자바의 정석 기초편 ch8
- 자바의 정석 기초편 ch3
- 스프링 db2 - 데이터 접근 기술
Archives
- Today
- Total
나구리의 개발공부기록
자바의 정석 기초편 ch7 - 42 ~ 52[내부클래스의종류,특징,선언, 내부클래스의 제어자와 접근성, 익명클래스] 본문
유튜브 공부/JAVA의 정석 기초편(유튜브)
자바의 정석 기초편 ch7 - 42 ~ 52[내부클래스의종류,특징,선언, 내부클래스의 제어자와 접근성, 익명클래스]
소소한나구리 2023. 11. 30. 12:451) 내부클래스
- 클래스 안의 클래스
(1) 장점
- 내부 클래스에서 외부 클래스의 멤버들을 외부클래스의 객체를 만들지 않고 접근이 가능함
- 코드의 복잡성을 줄일 수 있음 - 일종의 캡슐화
- B클래스를 굳이 밖에서 사용할 일이 없을 때 내부클래스로 생성 -> 별도의 방법으로 사용은 가능함
class A { // B의 외부클래스
....
class B { // A의 내부클래스 - 객체생성없이도 A의 멤버 접근 가능
...
}
...
}
(2) 내부 클래스의 종류별 유효범위
- iv = 내부클래스
- cv = static 내부 클래스
- lv = 메서드안에 선언된 내부 클래스
class outer {
int iv = 0; // iv = 내부클래스와 동일
static int cv = 0; // cv = static 내부클래스와 동일
void myMethod() {
int lv = 0; // lv = 메서드 안에 선언된클래스(지역클래스)와 동일
}
}
class outer {
class InstanceInner { } // 내부클래스 = iv와 동일
staic class StaticInner { } // static내부 클래스(스태틱클래스 = cv와 동일
void myMethod() {
class localInner { } // 메서드 안에 선언된클래스(지역클래스) = lv
}
}
(3) 내부 클래스의 제어자와 접근성
- 내부 클래스의 제어자는 변수에 사용 가능한 제어자와 동일하게 전부 사용 가능
- 내부 클래스에 static멤버를 담을 수 있는 것은 static 내부클래스만 허용 - 핵심(상수는 예외)
class ex7_12 {
class InstanceInner {
int iv = 100;
// static int cv = 100; // 에러! static변수를 선언할 수 없다.
final static int CONST = 100; // final static은 상수이므로 허용
}
static class StaticInner {
int iv = 200; // static 내부 클래스의 iv
static int cv = 200; // static내부클래스만 static멤버를 정의할 수 있다.
}
void myMethod() {
class LocalInner {
int iv = 300;
// static int cv = 300; // 에러! static변수를 선언할 수 없다.
final static int CONST = 300; // final static은 상수이므로 허용
}
}
public static void main(String args[]) {
System.out.println(InstanceInner.CONST);
System.out.println(StaticInner.cv);
// System.out.println(LocalInner.CONST); // 에러(지역내부클래스는 메서드 밖에서 사용 불가)
}
}
** 참고
- 상수(final)인 경우에는 static을 붙히는 경우가 많지만 경우에따라 조금 제어자의 적용 여부가 달라질 수 있음
- 값이 변하지 않지만 공통적으로 사용하지 않는 값 - static 안붙힘
- 값이 변하지 않지만 공통적으로 사용하는 값 - static 붙힘
- 상수는 constant pool이 있어서 별도의 공간에 저장되어 메서드가 종료 되어도 상수는 남아있으므로 계속 사용 가능함
(4) 예제1
- 내부 클래스들의 종류별 객체 생성
- 내부 클래스들의 유효범위가 iv, cv, lv와 같기 때문에 이들의 특성이 그대로 적용된다고 보면됨
- 내부클래스는 객체를 생성해야하고, 스태틱 클래스는 바로 접근이 가능함
- 스태틱 메서드에서는 내부 클래스는 바로 접근이가능하지만 외부클래스는 객체를 생성해야만 접근이가능한 반면 인스턴스 메서드에서는 둘다 직접 접근이 가능함
class Ex7_13 {
class InstanceInner {} // 내부클래스
static class StaticInner {} // 스태틱 내부클래스
// 인스턴스멤버 간에는 서로 직접 접근이 가능하다.
InstanceInner iv = new InstanceInner();
// static 멤버 간에는 서로 직접 접근이 가능하다.
static StaticInner cv = new StaticInner();
// static멤버는 인스턴스멤버에 직접 접근할 수 없음. cv는 iv,im 사용 불가한 것과 같은 이치
static void staticMethod() {
// InstanceInner obj1 = new InstanceInner(); // static메서드에서 생성 불가
StaticInner obj2 = new StaticInner();
// 굳이 접근하려면 아래와 같이 객체를 생성해야 함
// 내부클래스는 외부 클래스를 먼저 생성해야만 생성할 수 있음
Ex7_13 outer = new Ex7_13();
InstanceInner obj1 = outer.new InstanceInner();
}
// 인스턴스메서드에서는 인스턴스멤버와 static멤버 모두 접근 가능gka
void instanceMethod() {
InstanceInner obj1 = new InstanceInner();
StaticInner obj2 = new StaticInner();
// 메서드 내에 지역적으로 선언된 내부 클래스는 외부에서 접근할 수 없음
// LocalInner lv = new LocalInner();
}
void myMethod() {
class LocalInner {} // 지역 내부 틀래스
LocalInner lv = new LocalInner();
}
}
(5) 예제2
- 외부 클래스에 private 제어자가 붙어있어도 내부클래스에서는 접근 가능함
- 지역내부클래스(메서드 안의 클래스)에서 외부 클래스의 지역변수는(lv) 상수일때만 사용가능 했지만 JDK1.8(Java8) 부터는 변수도 사용 가능함
- 변수인데 값이 프로그램 실행 동안에 값이 바뀌지 않는 것은 상수로 간주함
class ex7_14 {
private int outerIv = 0;
private static int outerCv = 0;
class InstanceInner {
int iiv = outerIv; // 외부 클래스의 private멤버도 접근 가능함
int iiv2 = outerCv;
}
// 스태틱 클래스는 외부 클래스의 인스턴스멤버에 접근할 수 없음
static class StaticInner {
// int siv = outerIv;
static int scv = outerCv;
}
void myMethod() {
int lv = 0; // 값이 바뀌지 않는 변수는 상수로 간주
final int LV = 0; // JDK1.8부터 final 생략 가능
// lv = 3 이런식으로 중간에 값을 바꾸게 되면 에러
class LocalInner {
int liv = outerIv;
int liv2 = outerCv;
// 외부 클래스의 지역변수는 final이 붙은 변수(상수)만 접근가능했지만 바뀜
int liv3 = lv; // JDK1.8(Java8)부터 에러가 아니게 바뀌었음
int liv4 = LV; // OK
}
}
}
(6) 예제3
- 내부클래스는 객체를 생성하여 참조된 참조변수로 접근을 해야하고, 내부 객체를 생성하기 위해선 내부 클래스를 정의한 외부 클래스의 객체를 생성해야함
- 스태틱 내부 클래스는 클래프명으로 직접 접근하면 됨
- 컴파일하면 class파일이 5개 만들어짐
- 내부클래스는 외부클래스명+$+내부클래스명 으로 생성됨
- 지역내부클래스는 외부클래스명+$+숫자+내부클래스명으로 생성됨
class Outer2 {
class InstanceInner {
int iv = 100;
}
static class StaticInner {
int iv = 200;
static int cv = 300;
}
void myMethod() {
class LocalInner {
int iv = 400;
}
}
}
class ex7_15 {
public static void main(String[] args) {
// 인스턴스클래스의 인스턴스를 생성하려면 외부 클래스의 인스턴스를 먼저 생성
Outer2 oc = new Outer2(); // 외부클래스 인스턴스 생성
Outer2.InstanceInner ii = oc.new InstanceInner(); // 내부클래스의 인스턴스 생성
System.out.println("ii.iv : "+ ii.iv); // iv출력
// 외부클래스명.내부클래스명.cv명
System.out.println("Outer2.StaticInner.cv : "+Outer2.StaticInner.cv); //cv출력
// 스태틱 내부 클래스의 iv는 내부클래스 객체를 바로 생성(외부클래스 객체 생성안해도 됨)
// 외부클래스.내부클래스명 변수명 = new 외부클래스명.내부클래스명();
Outer2.StaticInner si = new Outer2.StaticInner();
System.out.println("si.iv : "+ si.iv);
}
}
// 컴파일하면 class파일이 5개 만들어짐
// 내부클래스에는 외부클래스명+$+내부클래스명
// 지역내부클래스에는 외부클래스명+$+숫자+내부클래스명으로 생성
(7) 예제4
- 변수의 이름이 같을 때 구별 방법
- 외부클래스 변수 - 외부클래스명.this.iv명
- 내부클래스 변수 - this.iv명
- 지역변수 - lv명
class Outer3 {
int value = 10; // Outer3.this.value (외부클래스의 iv)
class Inner {
int value = 20; // this.value (내부클래스의 iv)
void method1() {
int value = 30;
System.out.println(" value :" + value);
System.out.println(" this.value :" + this.value);
System.out.println("Outer3.this.value :" + Outer3.this.value);
}
} // Inner클래스의 끝
} // Outer3클래스의 끝
class ex7_16 {
public static void main(String args[]) {
Outer3 outer = new Outer3();
Outer3.Inner inner = outer.new Inner();
inner.method1();
}
}
2) 익명클래스(anonymous class)
- 이름이 없는 일회용 클래스 -> 정의와 생성을 동시에함
- 익명클래스도 내부클래스의 일종이라고 볼 수 있음
- 자신의 이름이 없어서 조상의 이름으로 객체를 구현함
- 컴파일하면 클래스명이 없으므로 숫자로 표현됨 -> 외부클래스명+$+숫자
- 익명클래스가 정의되고 해당 전체 문장이 끝날때 세미콜론을 붙혀야함, 즉 익명 클래스를 정의할때 ;을 붙히는게 아니라 익명클래스를 정의하고 문장이 마무리 되었기 때문에 ;을 붙히는 것임
(1) 예제1
// 기존의 클래스 정의 및 객체 생성 방법
class MyClass extends Object { /* 멤버선언 등 */ } // 클래스정의
MyClass mc = new MyClass(); // 객체생성
// 익명 클래스를 생성
new 조상클래스이름() {
// 멤버선언
}; // 문장이 종료 되었으므로 세미콜론을 붙혀야함
// 또는
new 구현인터페이스이름() {
// 멤버선언
}; // 문장이 종료 되었으므로 세미콜론을 붙혀야함
(2) 예제2
- 다양한 익명 클래스 정의 방법
class Ex7_17 {
Object iv = new Object(){ // 익명 클래스를 생성하여 iv에 참조값을 저장
void method(){}
};
// 익명 클래스를 생성하여 static 변수인 cv에 참조값을 저장
static Object cv = new Object(){
void method(){}
};
void myMethod() {
// 메서드 내부에 익명 클래스를 정의하여 lv에 참조값을 저장
Object lv = new Object(){
void method(){}
};
}
}
(3) 예제3
- 일반 클래스 -> 익명클래스를 전환
- 클래스를 일회성으로 사용해야할 때 사용됨
- 즉 재사용할 필요가 없이 단발성인 경우에 클래스를 선언하지 않고 즉시 사용할 때 사용한다고 보면 됨
import java.awt.*;
import java.awt.event.*;
class Ex7_18 {
public static void main(String[] args) {
Button b = new Button("Start");
b.addActionListener(new EventHandler());
}
}
class EventHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("ActionEvent occurred!!!");
}
}
//익명클래스로 전환 시
class Ex7_18 {
public static void main(String[] args) {
Button b = new Button("Start");
b.addActionListener(new ActionListener() { // 클래스의정의와 객체생성을 동시에
public void actionPerformed(ActionEvent e) {
System.out.println("ActionEvent occurred!!!");
}
});
}
}
** 출처 : 남궁성의 정석코딩_자바의정석_기초편 유튜브 강의
'유튜브 공부 > JAVA의 정석 기초편(유튜브)' 카테고리의 다른 글
자바의 정석 기초편 ch8 - 7 ~ 10[printStackTrace(), 멀티 catch블럭, 예외 발생 시키기] (0) | 2023.12.04 |
---|---|
자바의 정석 기초편 ch8 - 1 ~ 6[프로그램오류, 예외 클래스의 계층구조,예외처리하기, try-catch문의 흐름] (2) | 2023.12.04 |
자바의 정석 기초편 ch7 - 39 ~ 41[인터페이스의 장점, 인터페이스의 디폴트메서드] (0) | 2023.11.29 |
자바의 정석 기초편 ch7 - 35 ~ 38 [인터페이스의 선언, 상속, 구현, 인터페이스와 다형성] (0) | 2023.11.29 |
자바의 정석 기초편 ch7 - 31 ~ 34[추상 클래스, 추상 메서드, 추상클래스의작성1~2] (0) | 2023.11.28 |