[[TableOfContents]] = 출처 ë° ê¸€ì“´ì´ = 출처 : http://www.javaworld.com/javaworld/jw-02-2002/jw-0201-java101.html? ê¸€ì“´ì´ : Jeff Friesen == Classes within classes == ìžë°”를 가르치는 ë™ì•ˆ, 나는 í•™ìƒë“¤ì´ 다른 ë©”ì˜ë“œ ì•ˆì— ë©”ì˜ë“œë¥¼ ì„ ì–¸í•˜ëŠ” ê²ƒì„ ë°œê²¬í–ˆë‹¤. 하지만, 파스칼과 다르게 ìžë°”ì—서는 중첩 í”„ë¡œì‹œì ¸ë¥¼ 허용하지 않는다. ê²°êµ, ìžë°” 컴파ì¼ëŸ¬ëŠ” outerMethod()ì•ˆì— innerMethod()ê°€ 존재하는 êµ¬ë¬¸ì„ ë§Œë‚¬ì„ ë•Œ ì—러를 ë°œìƒì‹œí‚¨ë‹¤. {{{~cpp void outerMethod() { void innerMethod() { } } }}} ë©”ì˜ë“œ 중첩과 달리, ìžë°”ì—서는 Java Language Specification1.1 부터 시작해서, 중첩 í´ëž˜ìŠ¤ë¥¼ 지ì›í•œë‹¤. ìžë°” 컴파ì¼ëŸ¬ëŠ” í•œ í´ëž˜ìŠ¤ê°€ 다른 í´ëž˜ìŠ¤ ì•ˆì— ìœ„ì¹˜í• ìˆ˜ 있는 ê²ƒì„ í—ˆìš©í•œë‹¤. ë‹¤ìŒ ì½”ë“œëŠ” outerClass í´ëž˜ìŠ¤ ì•ˆì— innerClassê°€ ì¤‘ì²©ëœ ê²ƒì„ ë³´ì—¬ì£¼ëŠ” ì˜ˆì œ 코드ì´ë‹¤. {{{~cpp class outerClass { class innerClass { } } }}} 왜 ìžë°”는 중첩 í´ëž˜ìŠ¤ë¥¼ 지ì›í–ˆê³ , ìžë°”ê°€ 지ì›í•˜ëŠ” ì¤‘ì²©ëœ í´ëž˜ìŠ¤ì˜ 종류는 ë¬´ì—‡ì´ ìžˆì„까? ì´ ì§ˆë¬¸ì— ëŒ€í•œ ë‹µì€ ì¬ì´ ë°°í¬í•œ Inner Classes Specification 문서를 ì°¸ê³ í•˜ë©´ ì•Œ 수 ìžˆì„ ê²ƒì´ë‹¤. === Summary === 필드와 ë©”ì˜ë“œì™€ 마찮가지로, ìžë°”ì—서는 í´ëž˜ìŠ¤ê°€ 다른 í´ëž˜ìŠ¤ì˜ 멤버가 ë˜ëŠ” ê²ƒì„ í—ˆìš©í•œë‹¤. ì´ë²ˆ 달ì—는, Jeff Friesenì´ ìžë°”ì˜ í´ëž˜ìŠ¤ ì¤‘ì²©ì— ëŒ€í•´ 알아본다. 그는 중첩 í´ëž˜ìŠ¤ë¥¼ 네 분류로 나타낸다. 최ìƒìœ„ í´ëž˜ìŠ¤(TopLevel Class), ì¸ìŠ¤í„´ìŠ¤ 내부 í´ëž˜ìŠ¤(Instance Inner Class), ì§€ì— ë‚´ë¶€ í´ëž˜ìŠ¤(Local Inner Class), ìµëª… 내부 í´ëž˜ìŠ¤(Anonymous Inner Class)ê°€ 그것ì´ë‹¤. === Glossary === * 최ìƒìœ„ í´ëž˜ìŠ¤(TopLevel Class) : ì¼ë°˜í´ëž˜ìŠ¤ì™€ ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ë¡œ 나눌 수 있다. ì¼ë°˜ í´ëž˜ìŠ¤ëŠ” 패키지 ë‚´ì˜ ë˜ëŠ” 아무 패키지ì—ë„ ì†í•˜ì§€ ì•Šì€ ì¼ë°˜í´ëž˜ìŠ¤ë¥¼ ë§í•œë‹¤. ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ëŠ” 다른 í´ëž˜ìŠ¤ì— ì¤‘ì²©ëœ ì •ì í´ëž˜ìŠ¤ë‚˜ ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ ë§í•œë‹¤.(ëª¨ë“ ì¸í„°íŽ˜ì´ìŠ¤ëŠ” ì •ì ì´ë‹¤) * ì¸ìŠ¤í„´ìŠ¤ 내부 í´ëž˜ìŠ¤(Instance Inner Class) : 다른 í´ëž˜ìŠ¤ì˜ ë¹„ì •ì 멤버로 ì •ì˜ëœ í´ëž˜ìŠ¤ë¥¼ ë§í•œë‹¤. * ì§€ì— ë‚´ë¶€ í´ëž˜ìŠ¤(Local Inner Class) : ë©”ì†Œë“œì˜ ì½”ë“œ ë¸”ë¡ ë‚´ì— ì„ ì–¸ëœ í´ëž˜ìŠ¤ë¥¼ ë§í•œë‹¤. * ìµëª… 내부 í´ëž˜ìŠ¤(Anonymous Inner Class) : 몸체만 ì •ì˜ë˜ê³ ì´ë¦„ì€ ì—†ëŠ” í´ëž˜ìŠ¤ë¥¼ ë§í•œë‹¤. === Why does Java support class nesting? === ìžë°”ê°€ í´ëž˜ìŠ¤ ì¤‘ì²©ì„ ì§€ì›í• 필요가 없다. 만약 Inner Classes Specification 문서를 공부했다면, 중첩 í´ëž˜ìŠ¤ì— 대한 ë¬¸ì œë“¤ì„ ë°œê²¬í• ê²ƒì´ë‹¤. 하지만 ìžë°”ì˜ ì¤‘ì²© í´ëž˜ìŠ¤ 지ì›ì€ ì ì–´ë„ ë‘가지 ì´ì ì´ ìžˆë‹¤. * 소스 ì½”ë“œì˜ íˆ¬ëª…ì„± ì¦ì§„ * ì´ë¦„ 충ëŒì˜ ê°ì†Œ 중첩 í´ëž˜ìŠ¤ëŠ” ì†ŒìŠ¤ì½”ë“œì˜ íˆ¬ëª…ì„±ì„ ì¦ì§„시킨다. ê°ì²´ì— ë°€ì ‘í•œ í´ëž˜ìŠ¤ ì„ ì–¸ì„ í• ìˆ˜ 있다는 ê²ƒì€ ì¡°ìž‘í•˜ê¸° 쉽게 ë§Œë“¤ê³ , í´ëž˜ìŠ¤ì˜ ë©”ì˜ë“œì—ì„œ ê°ì²´ì˜ 필드를 ì§ì ‘ ì ‘ê·¼í• ìˆ˜ 있게 하며 ê°ì²´ì˜ ë©”ì˜ë“œë¥¼ ì§ì ‘ 호출 있ë„ë¡ í•´ì¤€ë‹¤. ë¹„ë¡ private 필드와 ë©”ì˜ë“œ ì¼ì§€ë¼ë„ 가능하다. 그런 ì´ì ì„ ì´í•´í•˜ê¸° 위해서, Employee ê°ì²´ ì•ˆì— ì¡´ìž¬í•˜ëŠ” Job ê°ì²´ì˜ ë°°ì—´ì„ ë‚˜ì—´í•´ì•¼ 하는 í”„ë¡œê·¸ëž¨ì„ ê°€ì •í•´ë³´ìž. {{{~cpp // Listing 1. JobIterator1.java class Job { private String jobTitle; Job (String jobTitle) { this.jobTitle = jobTitle; } public String toString () { return jobTitle; } } class Employee { private String name; private Job [] jobs; private int jobIndex = 0; Employee (String name, Job [] jobs) { this.name = name; this.jobs = jobs; } String getName () { return name; } boolean hasMoreJobs () { return jobIndex < jobs.length; } Job nextJob () { return !hasMoreJobs () ? null : jobs [jobIndex++]; } } class JobIterator1 { public static void main (String [] args) { Job [] jobs = { new Job ("Janitor"), new Job ("Delivery Person") }; Employee e = new Employee ("John Doe", jobs); System.out.println (e.getName () + " works the following jobs:\n"); while (e.hasMoreJobs ()) System.out.println (e.nextJob ()); } } John Doe works the following jobs: Janitor Delivery Person }}} JobIterator1ì€ Job, Employee, JobIterator1 í´ëž˜ìŠ¤ë¡œ 구성ëœë‹¤. Job í´ëž˜ìŠ¤ëŠ” job 타ì´í‹€ì„ 캡ìŠí™” í•˜ê³ Employee ê°ì²´ëŠ” ê³ ìš©ì¸(employee) ì´ë¦„ê³¼ ì§ì—…ì„ ì €ìž¥í•˜ëŠ” ë°°ì—´ì„ ìºìŠí™” 한다. JobIterator1ì€ Jobê³¼ Employee ê°ì²´, ê·¸ë¦¬ê³ ê³ ìš©ì¸ì˜ ì´ë¦„ê³¼ ì§ì—…ì„ ì°ëŠ” main() ë©”ì˜ë“œë¥¼ í¬í•¨í•œë‹¤. Employee í´ëž˜ìŠ¤ì— 드러난 hasMoreJobs()와 nextJob() 함수를 ìžì„¸ížˆ ë³´ìž. ì´ í•¨ìˆ˜ë“¤ì€ ë°˜ë³µìž(Iterator)를 구성한다. Employee ê°ì²´ê°€ 초기화 ë ë•Œ, 내부 private ë©¤ë²„ì¸ jobs는 0으로 ì„¤ì •ëœë‹¤. 만약 ì¸ë±ìŠ¤ì˜ ê°’ì´ jobs ë°°ì—´ì˜ ê¸¸ì´ë³´ë‹¤ 작다면 hasMoreJobs() 함수는 TRUE를 리턴한다. nextJob() 함수는 ì¸ë±ìŠ¤ 배열로부터 Job ê°ì²´ë¥¼ 반환받기 위해서 ì¸ë±ìŠ¤ì˜ ê°’ì„ ì‚¬ìš©í•˜ê³ , ë™ì‹œì— ì¸ë±ìŠ¤ì˜ ê°’ì€ ë‹¤ìŒ ê°ì²´ì˜ 참조를 위해서 ì¦ê°€í•œë‹¤. JobIterator1 í´ëž˜ìŠ¤ëŠ” ë¬¸ì œê°€ 있다. 첫째, 완벽하게 ëë‚œ í›„ì— ìž¬ ì‹œìž‘ì„ í• ìˆ˜ 없다. 하지만, ì¸ë±ìŠ¤ì˜ ê°’ì„ 0으로 초기화 하는 reset() ì´ë¼ëŠ” 함수를 ì¶”ê°€í•¨ìœ¼ë¡œì¨ ì‰½ê²Œ ë¬¸ì œë¥¼ í•´ê²°í• ìˆ˜ ìžˆì„ ê²ƒì´ë‹¤. 둘째, ì¢€ë” ì‹¬ê°í•œ ë¬¸ì œëŠ” í•˜ë‚˜ì˜ Employee ê°ì²´ë¥¼ 위한 여러 ê°œì˜ ë°˜ë³µìž(Iterator)를 만드는 ê²ƒì´ ë¶ˆê°€ëŠ¥í•˜ë‹¤. ê·¸ ë¬¸ì œë¥¼ 해결하기 위해서, ì „í˜•ì 으로 개발ìžëŠ” Iteratorë¼ëŠ” í´ëž˜ìŠ¤ë¥¼ ì •ì˜í•œë‹¤. í•œë²ˆì˜ Iterator í´ëž˜ìŠ¤ê°€ ëë‚˜ê³ , í”„ë¡œê·¸ëž¨ì€ ìƒˆë¡œìš´ Iterator ê°ì²´ë¥¼ ë§Œë“¬ìœ¼ë¡œì¨ ìƒˆë¡œìš´ ë°˜ë³µì„ ì‹œìž‘í• ìˆ˜ 있다. ë˜í•œ 여러 ê°œì˜ Iterator ê°ì²´ë¥¼ ìƒì„±í•¨ìœ¼ë¡œì¨, í”„ë¡œê·¸ëž¨ì€ ê°™ì€ Employee ê°ì²´ì˜ job ë°°ì—´ì„ ì—¬ëŸ¬ 번 반복 수행 í• ìˆ˜ 있다. Listing2는 JobIteratorë¼ ëª…ëª…í•œ ë°˜ë³µìž í´ëž˜ìŠ¤ì˜ ì‚¬ìš©ì„ ë³´ì—¬ì¤€ë‹¤. {{{~cpp // JobIterator2.java class Job { private String jobTitle; Job (String jobTitle) { this.jobTitle = jobTitle; } public String toString () { return jobTitle; } } class Employee { private String name; private Job [] jobs; Employee (String name, Job [] jobs) { this.name = name; this.jobs = jobs; } String getName () { return name; } JobIterator getJobIterator () { return new JobIterator (jobs); } } class JobIterator { private Job [] jobs; private int jobIndex = 0; JobIterator (Job [] jobs) { this.jobs = jobs; } boolean hasMoreJobs () { return jobIndex < jobs.length; } Job nextJob () { return !hasMoreJobs () ? null : jobs [jobIndex++]; } } class JobIterator2 { public static void main (String [] args) { Job [] jobs = { new Job ("Janitor"), new Job ("Delivery Person") }; Employee e = new Employee ("John Doe", jobs); System.out.println (e.getName () + " works the following jobs:\n"); JobIterator ji = e.getJobIterator (); while (ji.hasMoreJobs ()) System.out.println (ji.nextJob ()); } } }}} JobIterator2는 JobIterator1ê³¼ ê°™ì€ ê²°ê³¼ë¥¼ ì¶œë ¥í•œë‹¤. 하지만 JobIterator2ê°€ Iterator 코드를 Employee í´ëž˜ìŠ¤ì—ì„œ JobIterator í´ëž˜ìŠ¤ë¡œ 옮긴 ê²ƒì´ ë‹¤ë¥´ë‹¤. ë˜í•œ, Employee í´ëž˜ìŠ¤ëŠ” 새로운 JobIterator ê°ì²´ 참조를 ë¦¬í„´í• getJobIterator() 함수를 ì„ ì–¸í•œë‹¤. JobIterator와 Employee í´ëž˜ìŠ¤ëŠ” ë°€ì ‘í•˜ê²Œ ì—°ê´€ëœ í´ëž˜ìŠ¤ë¼ëŠ” ê²ƒì„ ì¸ì§€í•˜ìž.(JobIterator í´ëž˜ìŠ¤ì˜ ìƒì„±ìžê°€ Employeeì˜ private ë©¤ë²„ì¸ job ë°°ì—´ì˜ ì°¸ì¡°ë¥¼ 요구한다) ë¹„ë¡ JobIterator2ê°€ 편리하게 JobIterator1ì˜ ë¬¸ì œë¥¼ 해결했지만, 새로운 í”„ë¡œê·¸ëž¨ì€ ìƒˆë¡œìš´ ë¬¸ì œë¥¼ 만들었다. Employee ê°ì²´ì™€ ê¹Šì´ ì—°ê´€ëœ JobIterator2는 ë…립ì ì¸ JobIteratorë¡œì¨ì˜ ì—í• ì„ í• ìˆ˜ 없게 ëœë‹¤. ë¹„ë¡ ìš°ë¦¬ì˜ ì˜ˆì œì—서는 사소한 ë¬¸ì œì´ì§€ë§Œ, 중대한 프로그램ì—서는 심ê°í•œ ë¬¸ì œì¼ ìˆ˜ 있다. ë°ì´í„° ê³µìœ ë¥¼ 만들기 위해서, 몇몇 í´ëž˜ìŠ¤ë“¤ì´ 완벽하게 다른 í´ëž˜ìŠ¤ë“¤ì— ì˜ì¡´í•œë‹¤ëŠ” ê²ƒì„ ì¸ì§€í•´ì•¼í•œë‹¤. ì˜ì¡´ í´ëž˜ìŠ¤ë“¤ì„ ê·¸ë“¤ì´ ì˜ì¡´í•˜ëŠ” í´ëž˜ìŠ¤ë“¤ ì•ˆì— ì„ ì–¸í•´ì•¼ í• ê²ƒì´ë‹¤. Listing3ì€ JobIterator í´ëž˜ìŠ¤ë¥¼ Employee í´ëž˜ìŠ¤ ì•ˆì— ì„ ì–¸í•˜ëŠ” ë°©ë²•ì„ ë³´ì—¬ì¤€ë‹¤. {{{~cpp class Job { private String jobTitle; Job (String jobTitle) { this.jobTitle = jobTitle; } public String toString () { return jobTitle; } } class Employee { private String name; private Job [] jobs; Employee (String name, Job [] jobs) { this.name = name; this.jobs = jobs; } String getName () { return name; } JobIterator getJobIterator () { return new JobIterator (); } class JobIterator { private int jobIndex = 0; public boolean hasMoreJobs () { return jobIndex < jobs.length; } public Object nextJob () { return !hasMoreJobs () ? null : jobs [jobIndex++]; } } } class JobIterator3 { public static void main (String [] args) { Job [] jobs = { new Job ("Janitor"), new Job ("Delivery Person") }; Employee e = new Employee ("John Doe", jobs); System.out.println (e.getName () + " works the following jobs:\n"); Employee.JobIterator eji = e.getJobIterator (); while (eji.hasMoreJobs ()) System.out.println (eji.nextJob ()); } } }}} JobIterator1,JobIterator2와 ê°™ì€ ê²°ê³¼ë¥¼ ì¶œë ¥í•˜ëŠ” JobIterator3는 중첩 í´ëž˜ìŠ¤ë¥¼ 묘사한다. Employee í´ëž˜ìŠ¤ëŠ” JobIterator í´ëž˜ìŠ¤ì˜ ì„ ì–¸ì„ í¬í•¨í•œë‹¤. JobIterator ì¤‘ì²©ì˜ ê²°ê³¼ëŠ” JobIteratorê°€ 바로 Employeeì˜ private ë©¤ë²„ì¸ jobs를 ì ‘ê·¼í• ìˆ˜ 있기 ë•Œë¬¸ì— ìƒì„±ìžë¥¼ 요구하지 않는다. JobIterator3 í´ëž˜ìŠ¤ëŠ” ë”ì´ìƒ ìƒì„±ìž í˜¹ì€ jobs 필드를 요구하지 않기 ë•Œë¬¸ì— JobIterator2ì˜ ì†ŒìŠ¤ 코드보다 다소 명확하다. 소스 ì½”ë“œì˜ íˆ¬ëª…ì„±ì˜ ì¦ì§„ì„ ë”하기 위해서, í´ëž˜ìŠ¤ ì¤‘ì²©ì˜ ë‘번째 ì´ì ì„ ê³ ë ¤í•´ë³´ìž. ì¤‘ì²©ëœ í´ëž˜ìŠ¤ë“¤ì´ 다른 í´ëž˜ìŠ¤ë“¤ ì•ˆì— ìžˆì„ ë•Œ, ì´ë¦„ 충ëŒì€ ê°ì†Œí•œë‹¤. Listing3ì„ ìžì„¸ížˆ ë³´ë©´, 최ìƒìœ„ í´ëž˜ìŠ¤ë“¤ì€ Job, Employee, JobIterator3ì´ë‹¤. ë˜í•œ Employee.JobIterator í´ëž˜ìŠ¤ê°€ 있다. 만약 우리가 Employee와 ê°™ì€ Levelì˜ JobIterator ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ ì¶”ê°€í•œë‹¤ê³ ìƒê°í•˜ë©´, Job, Employee, JobIterator3, JobIteratorê°€ 최ìƒìœ„ í´ëž˜ìŠ¤ì´ë‹¤. Employee.JobIterator와 JobIteratorê°€ 다른 ì´ë¦„ì„ ë‚˜íƒ€ë‚´ê¸° 때문ì—, ì´ë¦„ 충ëŒì˜ ë¬¸ì œëŠ” ë°œìƒí•˜ì§€ 않는다. === What nested classes does Java support? === ìžë°”ì—서는 중첩 í´ëž˜ìŠ¤ë¥¼ ë‘ ë¶„ë¥˜ë¡œ 나눈다. 중첩 최ìƒìœ„ í´ëž˜ìŠ¤(Nested Top-Level Class)와 중첩 내부 í´ëž˜ìŠ¤(Nested Inner Class)ê°€ 그것ì´ë‹¤. ë”ìš±ì´, ìžë°”는 내부 í´ëž˜ìŠ¤ë¥¼ í´ëž˜ìŠ¤ì˜ 멤버 í´ëž˜ìŠ¤(Member Class), ì§€ì— í´ëž˜ìŠ¤(Local Class), ìµëª… í´ëž˜ìŠ¤(Anonymous Class)ë¡œ 나눈다. 중첩 í´ëž˜ìŠ¤ë¥¼ ì´í•´í•˜ê¸° 위해서, ê° ì¹´í…Œê³ ë¦¬ë¥¼ ì´í•´í•´ì•¼í•œë‹¤. 우리는 중첩 최ìƒìœ„ í´ëž˜ìŠ¤ë¶€í„° ì¹´í…Œê³ ë¦¬ì— ëŒ€í•œ íƒí—˜ì„ 시작한다. ==== Nested Top-Level Classes ==== ë‹¹ì‹ ì´ ì–´ë–¤ 다른 í´ëž˜ìŠ¤ ë°–ì—ì„œ í´ëž˜ìŠ¤ë¥¼ ì„ ì–¸ í–ˆì„ ë•Œ, ìžë°”는 ê·¸ í´ëž˜ìŠ¤ë¥¼ 최ìƒìœ„ í´ëž˜ìŠ¤ë¼ê³ 간주한다. 만약 ë‹¹ì‹ ì´ ìµœìƒìœ„ í´ëž˜ìŠ¤ ì•ˆì— í´ëž˜ìŠ¤ë¥¼ ì„ ì–¸ í–ˆê³ ì¤‘ì²©ëœ í´ëž˜ìŠ¤ ì„ ì–¸ ì•žì— staticì´ë¼ëŠ” 키워드를 ì„ ì–¸ 했다면, ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ë¥¼ 위로 í• ê²ƒì´ë‹¤. ë‹¤ìŒ ì½”ë“œëŠ” 최ìƒìœ„ í´ëž˜ìŠ¤ì™€ ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ë¥¼ 묘사한다. {{{~cpp class TopLevelClass { static class NestedTopLevelClass { } } }}} static í•„ë„와 ë©”ì˜ë“œëŠ” ê°ì²´ì™€ ë…립ì ì´ë‹¤. ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ëŠ” ë˜í•œ 그런 ê°ì²´ë¡œë¶€í„° ë…립ì ì´ë‹¤. ë‹¤ìŒ ì½”ë“œë¥¼ ê³ ë ¤í•´ë³´ìž. {{{~cpp class TopLevelClass { static int staticField; int instanceField; static class NestedTopLevelClass { static { System.out.println ("Can access staticField " + staticField); // System.out.println ("Cannot access instanceField " + instanceField); } { System.out.println ("Can access staticField " + staticField); // System.out.println ("Cannot access instanceField " + instanceField); } } } }}} TopLevelClassì˜ staticField 변수는 ì ‘ê·¼í• ìˆ˜ 있다. 하지만, instanceField 변수는 ì ‘ê·¼í• ìˆ˜ 없다. NestedTopLevelClassê°€ TopLevelClassì˜ instanceField ë³€ìˆ˜ì— ì ‘ê·¼í• ìˆ˜ 없기 때문ì—, NestedTopLevelClass는 ì–´ë–¤ TopLevelClass ê°ì²´ì— ë…립ì ì´ë‹¤. {{{~cpp ì£¼ì˜ ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ëŠ” ì–´ë–¤ ì¤‘ì²©ëœ í´ëž˜ìŠ¤ì˜ ì¸ìŠ¤í„´ìŠ¤ 멤버(í•„ë“œ,ë©”ì˜ë“œ)를 ì ‘ê·¼í• ìˆ˜ 없다. }}} ë¹„ë¡ NestedTopLevelClassê°€ TopLevelClassì˜ ì¸ìŠ¤í„´ìŠ¤ í•„ë“œì— ì ‘ê·¼í• ìˆ˜ ì—†ë‹¤ê³ í•˜ë”ë¼ë„, static 키워드는 NestedTopLevelClassê°€ ìžì‹ ì˜ ì¸ìŠ¤í„´ìŠ¤ 필드를 ì„ ì–¸í•˜ê±°ë‚˜ NestedTopLevelClass ê°ì²´ë¥¼ 만드는 ê²ƒì„ ë°©ì§€í•˜ì§€ 않는다. Listing 4를 확ì¸í•´ë³´ìž. {{{~cpp //Listing 4. NestedTopLevelClassDemo.java // NestedTopLevelClassDemo.java class TopLevelClass { static class NestedTopLevelClass { int myInstanceField; NestedTopLevelClass (int i) { myInstanceField = i; } } } class NestedTopLevelClassDemo { public static void main (String [] args) { TopLevelClass.NestedTopLevelClass ntlc; ntlc = new TopLevelClass.NestedTopLevelClass (5); System.out.println (ntlc.myInstanceField); } } When run, NestedTopLevelClassDemo produces the following output: 5 }}} NestedTopLevelClassDemoì˜ ë©”ì¸ í•¨ìˆ˜ì—ì„œ NestedTopLevelClass 변수 ntlc를 만들었다. 변수를 ì„ ì–¸í•˜ê¸° 위한 문법(syntax)는 Listing3ì˜ Employee와 같다. ì¼ë°˜ì 으로, ì¤‘ì²©ëœ í´ëž˜ìŠ¤ íƒ€ìž…ì˜ ë³€ìˆ˜ê°€ í•„ìš”í• ë•Œ, 최ìƒìœ„ 중첩 í´ëž˜ìŠ¤ë¶€í„° ì 구분ìžë¥¼ ì´ìš©í•´ì„œ 최하위 중첩 í´ëž˜ìŠ¤ê¹Œì§€ë¥¼ 표현하면 ëœë‹¤. 예를 들면 다ìŒê³¼ 같다. Nest1,Nest2,Nest3 3ê°œì˜ ì¤‘ì²© í´ëž˜ìŠ¤ê°€ ìžˆë‹¤ê³ ê°€ì •í•˜ê³ , Nest3ì˜ ì¸ìŠ¤í„´ìŠ¤ë¥¼ ìƒì„±í•˜ê³ ì‹¶ì„ ë•Œì—는 다ìŒê³¼ ê°™ì€ ë°©ë²•ì„ ì´ìš©í•˜ë©´ ëœë‹¤. Nest1.Nest2.Nest3 nestedClass = Nest1.Nest2.Nest3() ì´ì ì—ì„œ, ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ ì•ˆì— ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ë¥¼ ì„ ì–¸í• ìˆ˜ 있는지 ê¶ê¸ˆí• 것ì´ë‹¤. ë˜í•œ, 만약 ë‘ ê°œì˜ ì´ë¦„ê³¼ íƒ€ìž…ì´ ê°™ì€ ë³€ìˆ˜ê°€ ìžˆì„ ë•Œ 무슨ì¼ì´ ë°œìƒí• 지 ê¶ê¸ˆí• 것ì´ë‹¤. Listing 5를 확ì¸í•´ë³´ìž. {{{~cpp Listing 5. NestingAndShadowingDemo.java // NestingAndShadowingDemo.java class TopLevelClass { private static int a = 1; private static int b = 3; static class NestedTopLevelClass { private static int a = 2; static class NestedNestedTopLevelClass { void printFields () { System.out.println ("a = " + a); System.out.println ("b = " + b); } } } } class NestingAndShadowingDemo { public static void main (String [] args) { TopLevelClass.NestedTopLevelClass.NestedNestedTopLevelClass nntlc; nntlc = new TopLevelClass.NestedTopLevelClass. NestedNestedTopLevelClass (); nntlc.printFields (); } } When run, NestingAndShadowingDemo produces the following output: a = 2 b = 3 }}} NestingAndShadowingDemo를 컴파ì¼í•˜ê³ 실행하면 ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ ì•ˆì— ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ê°€ 중첩ë 수 있다는 ê²ƒì„ ì•Œ 수 있다. ë˜í•œ ê²°ê³¼ ê°’ì€ NestedTopLevelClassì˜ í•„ë“œê°€ TopLevelClassì˜ í•„ë“œì— ì˜í•´ì„œ ê°€ë ¤ì§„ë‹¤ëŠ” ê²ƒì„ ë³´ì—¬ì¤€ë‹¤. ê²°ë¡ ì 으로, NestedTopLevelClassì˜ í•„ë“œì˜ ê°’ 2를 ì°ëŠ”다. 'ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤'ì—서는 ì¤‘ì²©ëœ 'ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤'ì˜ ì¸ìŠ¤í„´ìŠ¤ í•„ë“œ í˜¹ì€ í´ëž˜ìŠ¤ì˜ ì¸ìŠ¤í„´ìŠ¤ ë©”ì˜ë“œë¥¼ í˜¸ì¶œí• ìˆ˜ 없다. ì¸ìŠ¤í„´ìŠ¤ 멤버 ì ‘ê·¼ì„ í•˜ê¸° 위해서, ìžë°”는 내부 í´ëž˜ìŠ¤(Inner Class)를 지ì›í•œë‹¤. 내부 í´ëž˜ìŠ¤(Inner Class)는 static 키워드를 내부 í´ëž˜ìŠ¤ë¥¼ ì„ ì–¸í• ìˆ˜ 없다는 ê²ƒì„ ì œì™¸í•˜ë©´ ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ì™€ 비슷하다. 우리는 ì¸ìŠ¤í„´ìŠ¤ 내부 í´ëž˜ìŠ¤ ì¹´í…Œê³ ë¦¬ë¥¼ 시작해서 내부 í´ëž˜ìŠ¤ì— 대해 공부한다. {{{~cpp Tip 둘러싼(enclosing) í´ëž˜ìŠ¤ ë°–ì—ì„œ í´ëž˜ìŠ¤ì˜ 코드 ì ‘ê·¼ì„ ì œí•œí•˜ê¸° 위해서 private, protected, public 키워드로 ì¤‘ì²©ëœ ìµœìƒìœ„ í´ëž˜ìŠ¤ë¥¼ ì„ ì–¸í• ìˆ˜ 있다. }}} ==== Instance Inner Class ==== = Thread = * ["neocoin"]:ì•„ Inner Classì— ê´€ë ¨í•œ 문서를 한번 ë’¤ì ¸ ë³´ê³ ì‹¶ì—ˆëŠ”ë° ì •ë§ ê°ì‚¬í•©ë‹ˆë‹¤. --ìƒë¯¼ ---- ["Java"]