Test113~Test120 + Test121(중첩클래스 마지막)
중첩 클래스란 클래스 안에 다른 클래스가 설계되어 있는 형태로
클래스 내부에서만 사용할 보조 클래스가 필요한 경우
클래스를 중첩하여 프로그램의 구조를 보다 간단하고 알아보기 쉽도록
만들 수 있게 되는데 이러한 클래스를 중첩 클래스라 한다.
이는 특정 클래스를 자신의 클래스 내부적인 용도로만
사용할 목적으로 쓰이는데
특정 클래스를 마치 자신의 멤버 변수나 메소드처럼 사용할 수 있게 한다.
클래스 내부에...『public static class 클래스명』
중첩 클래스를 감싸는 외부 클래스의 {} 안에
static 을 붙인 새로운 클래스를 설계하는 것으로
모든 접근제어지시자를 사용할 수 있다.
static 중첩 클래스가 포함하고 있는 메소드에서는
(외부 클래스의 객체를 생성하지 않은 상태)
클래스 변수와 클래스 메소드만 접근할 수 있다.
// outer 클래스
class Test
{
static int a = 10; //-- static 변수
int b = 20; //-- 인스턴스 변수
// inner 클래스
public static class StaticNested //-- static 클래스 //a 와 static클래스는 태어나는 시점 같음
{ //그러나 인스턴스 b와 print는 아직 태어난지아닌지 세모
int c = 30; //--인스턴스 변수
void write() //--인스턴스 메소드
{
System.out.println("write()...");
System.out.println("a : " + a);
//System.out.println("b : " + b); //-- check~!!!에러 발생
System.out.println("c : " + c);
}
}//end class StaticNested
void print()
{
StaticNested sn = new StaticNested();
sn.write();
}
}//end class Test
// main() 메소드를 포함하고 있는 외부의 다른 클래스
public class Test118
{
public static void main(String[] args)
{
Test ob1 = new Test();
ob1.print();
//--==>>write()...
// a : 10
// c : 30
//StaticNested ob2 = new StaticNested();
//--==>> 에러 발생(컴파일 에러)
// ※ 중첩 내부 클래스는 외부에서 단독으로 객체를 생성한다.
// 단, 위와 같은 방법으로 객체를 생성해서는 안되고
// 클래스 메소드를 호출하는 것과 같은 방식을 통해
// 접근하여 인스턴스를 생성할 수 있도록 처리해야 한다.
//Test.a;
Test.StaticNested ob2 = new Test.StaticNested(); //-- check~!!!
ob2.write();
//--==>>write()...
// a : 10
// c : 30
}
}
클래스 내부에...『public class 클래스명』
//outer 클래스
class Test2
{
static int a = 10; // 전역변수, Test2의 멤버변수, static변수(class변수, 클래스 변수)
int b = 20; // 전역변수, Test2의 멤버변수, non-static변수(instance변수, 인스턴스변수)
void write() // -> 첫 번째 write() 메소드
{
System.out.println("write()...①");
final int c = 30; // 지역변수, 상수화된 변수(값이 변하지 않는 변수)
int d = 40; // 지역변수, 값이 수시로 변할 수 있는 변수
// 메소드 안에 존재하는 또다른 클래스(로컬 클래스, 지역 클래스, local class)
//inner 클래스
class LocalTest //class설계로를 여기에 작성한것 뿐이지 인스턴스 생성되는것은 아님! d 몇살인지 물어지마~!!!
{
void write() // -> 두 번째 write() 메소드
{
System.out.println("write()...②");
System.out.println("a : " + a);
System.out.println("b : " + b);
System.out.println("c : " + c);
//System.out.println("d : " + d); //--==>> check~!!! 에러 발생(컴파일 에러) ===> d가 얼마가 될지 모른다! 그래서 접근은 막아논것!
}
}// end class LocalTest
// ※ 변수 c 와 변수 d 는 둘 다 지역변수 이지만....
// c는 final 변수이기 때문에...
// 두 번째 write() 메소드에서 접근하는 시점에서 언제이더라도(즉, 언제 접근하더라도)
// 30 의 고정된 값임을 보장받을 수 있다.
// 반면에, d 는 그 값이 수시로 변동될 수 있는 상황이므로
// LocalTest 클래스의 인스턴스 생성 시점을
// 강제로 확정할 수 없기 때문에(즉, 언제다 라도 보장할 수 없기 때문에)
// d 에 접근하는 것은 피해야 한다.
d = 20; //--20
LocalTest ob1 = new LocalTest();
ob1.write(); //-- 두 번째 write() 메소드 호출
d += 10; //-- 30
}//end write
}// end Test2
// main() 메소드를 포함하고 있는 외부의 다른 클래스
public class Test119
{
public static void main(String[] args)
{
Test2 ob2 = new Test2();
ob2.write();
//-- write()...①
// write()...②
// a : 10
// b : 20
// c : 30
}
}
클래스가 아닌 메소드 내부에.... 『public class 클래스명』 or 『public static class 클래스명』
//outer
class InnerOuterTest
{
static int a = 10;
int b = 20;
//inner
class InnerNested
{
int c = 30;
void write()
{
System.out.println("inner의 write()...");
System.out.println("a : " + a);
System.out.println("b : " + b);
System.out.println("b : " + c);
}
}// end class InnerNested
void write()
{
System.out.println("outer의 write()...");
InnerNested ob1 = new InnerNested();
ob1.write();
}
}// end class InnerOuterTest
// main() 메소드를 포함하고 있는 외부의 다른 클래스
public class Test120
{
public static void main(String[] args)
{
//outer의 인스턴스 생성
InnerOuterTest ob2 = new InnerOuterTest(); //-- 앞에서 본 로컬처럼 확인할 것 없음~!!
ob2.write(); //-- outer의 write() 메소드 호출
// Test118.java에서 생성한 방법으로 시도 // static이 붙어있는 문법이여야 가능
//InnerOuterTest.InnerNested ob3 = new InnerOuterTest.InnerNested();
//--==>> 에러 발생 (컴파일 에러)
// 일반적인 인스턴스 생성 방법으로 시도 // 일반적인 인스턴스 생성문법인데 안댐
//InnerNested ob4 = new InnerNested();
//--==>> 에러 발생 (컴파일 에러)
// ※ 중첩 내부 클래스(static 중첩 클래스) 와는 달리
// 외부 클래스의 인스턴스(객체)를 사용하지 않고
// 단독으로 내부 클래스의 인스턴스 생성하는 것은 불가능하다.
// 그러면 외부클래스 인스턴스를 사용하면 내부 클래스 인스턴스 생성은 가능하다는 것~!!
// ※ check~!!!
// ※ test118.java 파일과 비교할 것~!!!
// 『new InnerOuterTest().new InnerNested();』 //--check~!!!! ★ 꼭 기억하기 ★
InnerOuterTest.InnerNested ob5 = ob2.new InnerNested();
ob5.write();
//--==>>inner의 write()...
// a : 10
// b : 20
// b : 30
InnerOuterTest.InnerNested ob6 = new InnerOuterTest().new InnerNested();
ob6.write();
//--==>>inner의 write()...
// a : 10
// b : 20
// b : 30
/*
outer클래스명.inner클래스명 참조변수명 = new outer생성자().new inner생성자();
*/
// cf) static -> 중첩 내부 클래스
// Test.StaticNested ob = new Test.StaticNested();
// outer클래스명.inner클래스명 참조변수명 = new outer클래스명.inner생성자();
}
}
→ 잠시 사용하고 버리는 클래스
이름 없는 클래스
클래스 또는 인터페이스에 대한 객체를 생성하면서
바로 클래스 또는 인터페이스를 정의하는 클래스.
정의하는 부분과 생성하는 부분이 하나로 묶어져
new 수식이 있는 곳에서 바로 클래스 또는 인터페이스를 정의하는 것을 의미한다.
new
{
...
};
awt 나 안드로이드 이벤트 처리에서 일반적으로 사용
상위 클래스 메소드를 하나 정도 재정의할 필요성이 있을 때 사용
클래스의 객체가 필요하면 또 다시 클래스를 생성해야 하는
번거로움 때문에 익명의 클래스를 생성하여 처리한다.
new 상위클래스의 생성자()
{
접근제어지시자 자료형 메소드()
{
...;
}
}; //← 세미콜론 check~!!!
*/
//import java.lang.*;
class Test3 //extends Object //-- 모든 클래스는 오브젝트라는 클래스를 상속받음!!
// 근데 이러면 자바 다중 상속 부분에서 이건 예외인가?
// 아니다! 가장 상위클래스가 오브젝트라는 클래스이기 때문에 모든 클래스의 조상클래스다!
{
/*
Object 클래스의 멤버들...
...
public String toString()
{
...;
}
*/
public Object getString()
{
/*
Object result;
result = new Object();
return Object; // == return result;
*/
/* 위에 구문이랑 같은 구문
return new Object();
------------ Object 형
*/
return new Object()
{
public String toString()
{
return "익명의 클래스...";
}
}; // 세미클론 꼭 check~!!!
}//end getString()
}//end class Test3
public class Test121 //extends Object
{
/*
Object 가 갖고있는 멤버들...
*/
public static void main(String[] args)
{
Test3 ob1 = new Test3();
Test3 ob2 = new Test3();
System.out.println(ob1.toString()); //오브젝트로부터 상속받은 투스트링메소드를 상속받아서 사용하고 있는것!
//--==>> Test3@15db9742
Test121 ob3 = new Test121();
System.out.println(ob3.toString()); //오브젝트로부터 상속받은 투스트링메소드를 상속받아서 사용하고 있는것!
//--==>> Test121@6d06d69c
System.out.println(ob2.getString());
//--==>> 익명의 클래스...
}
}