• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java 정리 16

04 Dec 2018

Reading time ~6 minutes

Java 정리 16 - inner classes, import


inner class

  • Event를 처리하기 위해 만들어진 클래스들
    • jdk 1.2에서부터 추가된 문법
  • 클래스를 인스턴스 변수처럼 사용할때 사용
  • Event를 화면 디자인클래스에서 생성하고 처리할 때
    • 해당 화면에 대해서만 이벤트를 처리할 때 사용
  • 안쪽 클래스의 접근지정자는 public으로 부여
  • 안쪽 클래스들은 바깥 클래스의 자원을 마음대로 사용가능
    • 바깥 클래스에서 바로 사용 불가
      • 객체화해서 사용 가능(일반적 객체화형태 아님)

01

// 1. 바깥 클래스 객체화
클래스명 객체명 = new 생성자();

// 2. 안쪽 클래스 객체화 - 바깥클래스 객체가 필수
[바깥클래스명.]안쪽클래스명 객체명 = 바깥클래스의객체명.new 안쪽클래스의생성자();

// 1
Outer out = new Outer(); 

// 2
Outer.Inner in = out.new Inner(); 
public class Outer {
  
  int i;
  public Outer() {
    System.out.println("바깥 클래스의 생성자");
  }
  
  public void outMethod() {
    System.out.println("바깥 클래스의 method,  i="+i);
    // 안쪽클래스를 객체화
    Outer.Inner in = this.new Inner();
    in.inMethod();
  }
  
  ////////////////////// 안쪽 클래스 시작  ////////////////////////
  public class Inner {
    int j;
    public Inner() {
        System.out.println("안쪽 클래스의  생성자");
    }
    public void inMethod() {
        // 안쪽클래스에선 바깥클래스의 변수,  method를 사용가능
        System.out.println("안쪽 클래스의 method,  j="
                  +j+", 바깥 클래스의 자원 i="+i);
    }
  }
  ////////////////////// 안쪽 클래스 끝  //////////////////////////
  
  public static void main(String[] args) {
    // 1. 바깥 클래스의 객체화
    Outer out = new Outer();
    out.i = 10;
    out.outMethod();
    
    // 안쪽클래스의 자원을 직접 접근사용불가
    // out.j = 20;
    // out.inMethod();
    
    // 2. 안쪽 클래스의 객체화(바깥 클래스  객체사용)
    // 바깥클래스명.안쪽클래스명 객체명 = 바깥클래스의객체명.new 안쪽생성자();
    // 바깥클래스명은  생략할 수 있다
    // Outer.Inner in = out.new Inner();
    Inner in = out.new Inner();
    
    in.j = 12;
    in.inMethod();
  }
}

nested class (중첩 클래스)

  • 안쪽 클래스를 static 변수처럼 사용할 때 사용
  • 이벤트를 공용 이벤트로 처리할 때
  • 내부 클래스의 자원을 가급적이면 static으로 만들어 사용.
    • static class라고 내부도 모두 static인게 아님.
    • 자원 중 static인 것만 객체화 없이 사용 가능
      • static 안쓰면 객체화 필요
    • 클래스명.변수명 또는 클래스명.메소드명() 형태로 사용

02

/**
* 내부클래스를 static 변수처럼 사용할 수 있는 중첩클래스(nested class)
*/
public class NestedOuter {
  
  int i;
  static int j;

  public NestedOuter() {
    System.out.println("바깥클래스 생성자");
  }
  
  public void outInstanceMethod() {
    System.out.println("바깥클래스의 instance method");
  }
  
  public static void outStaticMethod() {
    System.out.println("바깥클래스의 static method");
  }
  
  /////////////////////// Nested class 시작 ///////////////////
  public static class NestedInner {
    // int instance_i; // instance 변수, instance 생성 권장안함
    static int instance_j; // static 변수
    
    /*public NestedInner() { // static 클래스이므로 인스턴스화 X
        System.out.println("중첩클래스 생성자");
    }*/
    
    public void inMethod() { // 객체화없이 사용불가
      System.out.println("안쪽 클래스의 instance method");
    }
    
    public static void inStaticMethod() {
      System.out.println("안쪽 클래스의 static method");
      // i는 인스턴스 변수라 직접 사용불가(객체화 필요)
      System.out.println("바깥클래스의 자원 사용 "
              + "i=사용불가, j="+NestedOuter.j);
      // outInstanceMethod(); // 인스턴스 메소드라 사용불가
      NestedOuter.outStaticMethod();
    }
  }
  /////////////////////// Nested class 끝 /////////////////////
  
  public static void main(String[] args) {

    // static 영역을 사용할 때에는 객체화없이 클래스명.변수명,
    // 클래스명.method명으로 사용(static 방식)
    
    // NestedInner.inMethod(); // 객체화 안해서 사용불가
    NestedInner.inStaticMethod();
    
    // static 이므로 중첩클래스는 객체화 권장안함
    // NestedInner ni = new NestedInner();
    // System.out.println(ni.instance_i);
    
  }
}
  • 컴파일 하면 .class파일(byte code) 생성
    • 바깥클래스명.class
      • Outer.class
    • 바깥클래스명$안쪽클래스명.class
      • 자바에서 ‘.’은 그 안을 의미, 혼동가능-> $사용
        • $붙으면 이너클래스
      • $는 자바언어 외부에서 자바언어 내부를 의미하는 기호
    • 파일명으로 nested인지 inner인지는 구분하기 힘듦.

03


local class

  • 안쪽 클래스를 지역변수처럼 사용할 때 사용
  • method안에 정의하는 클래스
    • method가 호출되었다고 객체가 생성되지 않는다.
  • 객체 중 생명이 가장 짧다.
  • 안쪽클래스에서 인스턴스 변수는 참조가능하나 지역변수, parameter는 final이 붙은 변수만 참조가능.
  • method 외부에서 접근이 불가능
  • Compile되면 바이트코드로 바깥클래스는 바깥클래스명.class, 로컬클래스는 바깥클래스명$1로컬클래스명.class
    • 1,2,3,4는 메소드

04

/**
* method안에 클래스를 정의하는 지역class 사용.
* 생성된 객체를 지역변수처럼 사용하는 클래스
*/
public class LocalOuter {
  int i;
  public LocalOuter() {
    System.out.println("바깥 클래스의 생성자");
  }
  public void method(int param_i, final int param_j) { //  parameter는 지역변수
    int local_i = 0;
    final int local_j = 0;
    /////////////////////// 지역 클래스 시작  //////////////////////////
    class Local {
      int loc_i;
      public Local() {
        System.out.println("지역 클래스의  생성자");
      }
      
      public void locMethod() {
        System.out.println("지역 클래스의  method");
        System.out.println("외부 클래스의 instance  변수 i="+i);
        
        // jdk 1.8이전은 final이 붙은 지역변수만  사용가능
        System.out.println("매개변수(parameter)  param_i="
                  +param_i+", param_j="+param_j);
        System.out.println("지역변수 local_i="
                  +local_i+", local_j="+local_j);
        // jdk1.8부터는 final이 붙지 않은  지역변수의 출력은 가능하지만
        // final이 붙지 않아도 값할당은 되지  않는다(final처럼 사용됨)
        // local_i = 2018;  
        // pram_i = 2018;
      }
    }
    /////////////////////// 지역 클래스 끝  ////////////////////////////
    // 지역클래스를 사용하려면 메소드에서 지역클래스  객체화 필요
    
    // 지역클래스의 객체화
    Local lo = new Local();
    
    // 생성된 객체로 클래스내 자원을 사용할 수 있다.
    // loc_i=100; // 직접 사용불가
    lo.loc_i=100;
    lo.locMethod();
    System.out.println(lo.loc_i);
    
    System.out.println("method 호출");
  }
  public static void main(String[] args) {
    LocalOuter lo = new LocalOuter();
    lo.method(4, 12);
  }
}

anonymous inner class

  • 익명 클래스(이름 없는 클래스)
  • 매개변수에 입력되는 값(argument, 인수 값)으로 클래스를 사용
  • 한번 호출로 작업이 종료되는 경우 사용
  • Compile되면 바이트코드로 바깥클래스는 바깥클래스명.class처럼 변환되고 익명클래스는 바깥클래스명$1.class처럼 숫자로 끝난다.
// interface를 매개변수로 받으면 절차가 많음
public interface AnonyInter {
  public String getName();
  public String getMsg();
}

// AnonyInter 구현하는 클래스 AnonyImple 생성
public class AnonyImpl implements AnonyInter{
  @Override
  public String getName() {
    return "쵸몬도";
  }
  
  @Override
  public String getMsg() {
    return "온뇨쇼";
  }
}


// useAnonyInter의 인수로 인터페이스 구현한 클래스 객체 전달
public class TestAnony{
     
  public void useAnonyInter(AnonyInter ai) {
    System.out.println(ai.getMsg()+" "+ai.getName());
  }
  public static void main(String[] args) {
        
    // interface는 객체화가 되지 않는다.
    // AnonyInter ai = new AnonyInter();
    
    // interface가 매개변수 였을 때
    // 1. 인터페이스를 구현한 클래스를 생성
    // 2. 구현클래스로 객체를 생성
    AnonyInter ai = new AnonyImpl(); // is-a
    
    // 3. 매개변수를 가진 메소드를 호출하기위해 객체생성
    TestAnony ta = new TestAnony();
    
    // 4. method 호출
    ta.useAnonyInter(ai);
  }
}
// anonymouse innerclass 문법
호출하는method명(new 구현인터페이스명|부모클래스명() { 
    // '{' 앞의 대상을 부모로 하는 이름 없는 클래스가 생성됨
    
    @Override
    method재정의() { ... }
    ...
    method정의() { ... }
});
public class TestAnony{
  
  public void useAnonyInter(AnonyInter ai) {
    System.out.println(ai.getMsg()+" "+ai.getName());
  }
  public static void main(String[] args) {
    TestAnony ta = new TestAnony();

     // anonymous inner class를 사용하면 class를 따로 만들 필요가 없다.
    ta.useAnonyInter(new AnonyInter() {
      @Override
      public String getName() {
        return "쵸묜도";
      }
      @Override
      public String getMsg() {
        return "온뇨쇼";
      }
    });
  }
}

import

  • 외부 package내의 다른 클래스나 interface를 참조하여 사용하기 위한 것.
  • java.lang package는 자동 import 된다.
  • package 선언과 class 선언 사이에서 import 수행
    • import를 하면 다른 패키지 클래스들을 같은 패키지에 있는 것처럼 패키지명 없이 사용가능해진다.
  • jdk 1.5부터는 static import 기능이 추가됨.
  • 주의
    • 패키지명은 다르나 클래스나 interface명이 같은 경우 하나만 import 받을 수 있다.
      • 나머지 하나는 full path(패키지명 모두 기술하는 것)로 처리
package 패키지명;

import 패키지명.*; // 특정 패키지내의 모든 클래스를 참조하는 것
import 패키지명.클래스명; // 특정 패키지내 하나의 클래스를 참조하는 방법(권장)
...

public class 클래스명 {
...
import java.util.List;
// 패키지는 다르나 이름이 같은 클래스는 둘 중 하나만 import  받을 수 있다.  
// import java.awt.List;

// 같은 이름의 클래스(interface)는 둘 중 많이  사용되는 것을 import로 처리하고,
// 적게 사용되는 것을 full path로 처리한다.
List list = null;            // java.util.List
java.awt.List list1 = null;  // java.awt.List

static import

  • 다른 클래스의 static 변수(상수) 또는 static method를 내 클레스에 존재하는 것처럼 사용할 때 사용
  • jdk 1.5부터 지원
import static 패키지명.클래스명.static변수;    // 변수나 상수 사용할 때
import static 패키지명.클래스명.static메소드;  // method 사용할 때
import static java.lang.Integer.MAX_VALUE;
//같은 이름의 상수는 하나만 import
//import static java.lang.Byte.MAX_VALUE;

import static java.lang.Integer.parseInt;
import static java.lang.System.out;

public class StaticImport {
  public static void main(String[] args) {
    // 클래스명 없이 메소드 호출
    int i = parseInt("20181204");
    out.println(i);
    out.println(MAX_VALUE);
  }
}


Java