W.A 저장소

서울대학교 교육 2일차. #2 본문

Programing

서울대학교 교육 2일차. #2

W.A 2010. 8. 11. 00:00

1. 내부 클래스(inner class)

클래스 내부에 클래스를 만들어서도 사용이 가능하다. 이렇게 사용하는 경우는 2가지가 있다. 밑의 소스를 보자.
class Nesting {
private int i = 1;
private static int si = 2;

static class Nested {
int j = 3;
private static int k = 4;

void print() {
//System.out.println( i ) // 오류
System.out.println( si ); 
System.out.println( j );
}
}
Nesting() {
System.out.println( Nested.k);
}
}

 
class NestedClassTest {
public static void main( String[] args ) {
Nesting.Nested nested = new Nesting.Nested();
System.out.println( nested.j );
}

위와 아래를 보면 거의 같은 걸으로 보일 것이다. 하지만 다른점은 밑의 내부클래스의 접근자가 다르다. 이렇게 쓰여 졌을 경우 내부클래스에 접근하기 위한 방법이 달라진다.

class Outer {
int i = 1;
static int si = 2;

public class Inner {
int j = 3;
//static int k;

public void print() [
System.out.println( i );
System.out.println( Outer.this.i );
System.out.println( si );
System.out.println( j );
}
}

public Outer() {
Inner inner1 = new Inner();
Inner inner2 = this.new Inner();
System.out.println( inner1.j );
}
}

class InnerClassTest {
public static void main( String[] args ) {
Outer outer = new Outer();
System.out.println( outer.i );

Outer.Inner inner = Outer. new Inner();
//Outer.Inner inner2 = new Outer.Inner(); // 오류
System.out.println( inner.j );
}
}

위와 같은 상황처럼 하여 접근할 때에는 Nesting.Nested nested = new Nesting.Nested();
아래와 같은 방법으로 접근할 때에는 Outer.Inner inner = Outer. new Inner();

이렇게 되어야 하는 이유는 위의 부분은 외부클래스와 내부클래스가 서로 독립적으로 생기지만
밑의 같은 경우에는 종족관계로 된다.


예1) 지역클래스
public Runnable getRunnable(final int i) {
class Command implements Runnable {
public void run() {
System.out.println( str + "," + i);
}
} return new command;
}

예2) 익명클래스
public Runnable getRunnalbe(final int i) { 
return new Runnable() {
System new Runnable() {
public void run()  {
System.out.println(str + ", " + i);
}
};
}
Runnalbe runner = new Runnable() {
public void run() {
System.out.println( str );
}
};

지금 위와같이 내부클래스에 2가지의 예를 들어보았다. 위의 예제와 밑의 예제가 다른 이유는 위의 클래스는 내부에서 사용하는 클래스에 대해서 이름을 부여했다는 점이고 밑의 클래스에서는 클래스의 이름을 지정하지 않고 그냥 바로 사용하였다. 이런것을 익명클래스라고 한다. 보통 코딩을 하면서 사용할 경우에는 위의 방법처럼 사용하기 보다는 밑의 익명클래스를 사용한다. 이유는 사람들이 대부분 내부에 클래스를 만들어서 사용하는 경우는 그 클래스에서만 필요로 하는 경우가 많기 때문에 그 클래스를 다른 외부에 노출을 시키지 않는부분이 대부분이라 꼭 고민을 하면서까지 클래스의 이름을 정할 필요가 없기 때문이다.

2. 예외처리

자 기본적인 예외처리의 구문을 보자.

try {
file = open("Some File");
} catch(SomeException e1) {
....// 요기요기.
} catch(OtherException e2) {
....// 요기두.
} finally {
file.close();
}

진한색으로 체크해 놓은 부분이 어떤 에외가 발생하였을때 처리하여 주는 부분이다.

간단하게 예를 들어보자면은. 사용자가 직접 정의하여서 쓰는 예이다.

class DivideException extends Exception {
public int x, y;
public DivideException(int x, int y) {
super( "Divide Exception" );
this.x = x;
this.y = y;
}
}

class ThrowTest {
public static void main( String[] args ) {
try {
int i = sumDivideDiff(8, 4) + sumDivideDiff(3, 3);
System.out.println("result = " + i);
} catch(DivideException e) {
System.out.println("value if i is not calculated: " + e.getMessage()
+ "(" + e.x + ", " + e.y + ")" );

}
System.out.println("End of main()" );
}

public static int sumDivideDiff(int x, int y) throws DivideException {
if ( x == y )
throw new DivideException(x, y);
return (x + y) / (x-y);
}
}
제일 위 첫번째 클래스가 사용자가 정의한 예외처리가 되는 부분이다. 순서는 이렇게 된다. 우선 메인 부분이 실행되면서 차근차근 진행이 되어진다. 그러며 중간에 sumDivideDiff가 호출이 된다. 그러면 sumDivideDiff부분으로 이동하여 실행하는데 x값과 y값이 같아지면서 사용자가 정의한 DivideException이 발생하게된다. 하지만 이 함수에서 처리를 하지 않고 자신을 호출한 곳으로 예외를 던진다. 그 부분이 밑의 sumDivideDiff함수에 진하게 표시한 부분이다. 이렇게 되면은 예외처리를 할때 어떻게 할 것인지를 메인함수의 catch부분에서 처리를 한다. 그 전에 제일 위에서 사용자가 정의한 부분의 이 밑에 sumDivideDiff부분에서 객체를 생성하며 보내 놓았기 때문에 main함수의 catch문에서 그 내용을 받아서 처리를 할 수 있게금 해둔것이다.

이번시간에는 내부클래스와 예외처리부분을 정리해 보았다. 아직 블로깅하는데에 미숙함이 많아서 도움이 되셨을지는 모르겠지만 이 것을 보시고 조금이라도 알아가셨으면 합니다.