Java 정리 16
04 Dec 2018
Reading time ~6 minutes
Java 정리 16 - inner classes, import
inner class
-
Event를 처리하기 위해 만들어진 클래스들
- jdk 1.2에서부터 추가된 문법
- 클래스를 인스턴스 변수처럼 사용할때 사용
- Event를 화면 디자인클래스에서 생성하고 처리할 때
- 해당 화면에 대해서만 이벤트를 처리할 때 사용
- 안쪽 클래스의 접근지정자는 public으로 부여
-
안쪽 클래스들은 바깥 클래스의 자원을 마음대로 사용가능
-
바깥 클래스에서 바로 사용 불가
- 객체화해서 사용 가능(일반적 객체화형태 아님)
-
바깥 클래스에서 바로 사용 불가
// 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 안쓰면 객체화 필요
- 클래스명.변수명 또는 클래스명.메소드명() 형태로 사용
/**
* 내부클래스를 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인지는 구분하기 힘듦.
-
local class
- 안쪽 클래스를 지역변수처럼 사용할 때 사용
-
method안에 정의하는 클래스
- method가 호출되었다고 객체가 생성되지 않는다.
- 객체 중 생명이 가장 짧다.
- 안쪽클래스에서 인스턴스 변수는 참조가능하나 지역변수, parameter는 final이 붙은 변수만 참조가능.
- method 외부에서 접근이 불가능
- Compile되면 바이트코드로 바깥클래스는
바깥클래스명.class
, 로컬클래스는바깥클래스명$1로컬클래스명.class
- 1,2,3,4는 메소드
/**
* 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(패키지명 모두 기술하는 것)로 처리
-
패키지명은 다르나 클래스나 interface명이 같은 경우 하나만 import 받을 수 있다.
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);
}
}