자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
[자바/SCJP]
출처 http://cafe.naver.com/edcxswqaz
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
[자바/SCJP]
출처 http://cafe.naver.com/edcxswqaz
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
[자바자격증/SCJP/자바학원]예외 처리(Exception Control) 2
예외 만들기
사용자가 직접 예외 클래스를 만들 수 있다. Exception 클래스를 상속하면 된다.
class MyException extends Exception{ MyException(String ErrorMessage){ // 생성자 super(ErrorMessage); // 부모 생성자 } } |
ErrorMessage는 에러 메시지로 화면에 출력할 내용이다. 사용자가 정의한 예외 객체를 던지려면 'throw'키워드를 사용하여 다음과 같이 한다.
throw new MyException("에러 메시지"); |
"MyException 객체를 만들어서 던져라"라고 이해하면 쉬울 것이다. 어떤 상황이 예외가 되는 조건이면 예외 객체를 만들어서 던지면 된다. 예외를 던지려면 메소드는 예외를 던지는 메소드로 정의해야 한다.
void f() throws MyException{ // 예외를 던지는 메소드
if(에러 조건) throw new MyException("에러 메시지"); ... } |
이제 예제를 해 보자.
Excep11.java |
|
class MyException extends Exception{
MyException(String ErrorMessage){
super(ErrorMessage);
}
}
public class Excep11{
static int avg(int a, int b) throws MyException{
if(a<0 || b<0) // x1
throw new MyException("음수 안 됨"); // x2
else if(a>100 || b>100) // x3
throw new MyException("너무 큼"); // x4
return (a+b)/2; // x5
}
public static void main(String[] args){
try{
System.out.println(avg(-10,20)); // x6
}catch(MyException e){
System.out.println(e); // x7
}
}
}
출력 결과 |
|
MyException: 음수 안 됨
x4행의 'avg(-10, 20)'을 호출하면 x1행의 조건이 true가 되어 x2행이 실행된다. 따라서 x6행으로 예외 객체가 던져진다. 즉, x6행에서 예외가 발생하여 x7행에서 에러 메시지를 출력한다. x4행을 수정하여 'avg(110,200)'을 호출하면 'MyException: 너무 큼'이 출력될 것이다. 'avg(10,20)'을 호출하면 예외가 발생하지 않고 x5행이 실행되어 15가 출력된다.
Exception의 부모 클래스가 왜 Throwable인지 이제 알 수 있을 것이다. 던질 수 있는 객체는 Exception과 Error이다.
|
연습 문제 |
|
1. 다음 코드를 실행했을 때 어떤 결과가 예상되는가? 직접 해보자.
int[] a; try{ a[10]= 100; }catch(ArrayIndexOutOfBoundsException ae){ System.out.println("A"); }catch(NegativeArraySizeException ne){ System.out.println("B"); } |
2. 다음 코드를 실행했을 때 어떤 결과가 예상되는가? 직접 해보자.
int[] a = new int[10]; try{ a[1]= 100; }catch(ArrayIndexOutOfBoundsException ae){ System.out.println("A"); }catch(Exception e){ System.out.println("B"); } |
3. 평균을 구하는 메소드 average는 0이상 100 이하의 세 정수를 인수로 취하여 평균을 반환한다. 0미만이거나 100초과인 정수가 인수로 넘어오면 예외를 던진다. 메소드 average를 완성해보자.
int average(int a, int b, int c) throws RuntimeException{
// OR(a<0, b<0, c<0) 이면 ArithmeticException을 던진다. // OR(a>100, b>100, c>100) 이면 IllegalArgumentException을 던진다.
return (a+b+c)/3; } |
4. 클래스 AvgException은 Exception을 상속하며 다음과 같다.
class AvgException extends Exception{ AvgException(){ super(); } AvgException(int number){ super("AvgException: "+number); } AvgException(String ErrorMessage){ super(ErrorMessage); } } |
인수 중에서 최대 값을 찾는 메소드 maxOfNaturalNumbers를 완성해 보자.
int maxOfNaturalNumbers(int a, int b, int c) throws AvgException{
// a가 0이하의 수이면 'new AvgException()'를 던진다. // b가 0이하의 수이면 'new AvgException(b)'를 던진다. // c가 0이하의 수이면 'new AvgException("마지막 인수")'를 던진다.
int m=a>b?a:b; return m>c?m:c; } |
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
[자바/JAVA/SCJP]예외 처리(Exception Control)
프로그램을 작성하여 실행하다 보면 프로그램이 다운될 때가 있다. 어떤 오류(Error)가 생겼기 때문인데 자바는 이런 오류가 발생하더라도 프로그램을 종료시키지 않고 유연하게 대처하는 방법을 제공한다. 하지만 모든 오류를 잡을 수 있는 것은 아니다. 자바는 잡을 수 있는 오류를 예외(Exception)라고 부른다.
예외가 발생하는 대부분의 이유는 프로그램을 잘못 작성했기 때문이지만 뜻하지 않게 발생할 수도 있다. 특히 입출력할 때 뜻하지 않은 예외가 많이 발생한다. 하지만 이런 예외도 마음껏 다룰 수 있다.
다음 코드를 컴파일하고 실행해보자.
public class Excep1{ public static void main(String[] args){ System.out.println("프로그램 시작"); int a=1,b=0; int c=a/b; // x1 System.out.println(c); System.out.println("프로그램 종료"); } } |
컴파일은 성공적으로 수행될 것이다. 하지만 실행할 때 다음과 같은 에러 메시지를 출력하고 프로그램은 종료할 것이다.
프로그램 시작 java.lang.ArithmeticException: / by zero at Excep1.main(Excep1.java:5) Exception in thread "main" |
x1행에서 0으로 나누었기 때문에 오류가 발생하여 프로그램이 비정상적으로 종료한 것이다. 자바는 이런 오류를 예외라고 부르고 객체로 취급한다. 예외가 발생했다는 것은 예외 객체가 생겼다는 말과 같다.
x1행에서 발생한 예외 객체는 ArithmeticException 클래스의 객체로 수학적 예외가 발생하였을 때 생성되는 객체이다.
try~catch
try~catch문을 사용하면 예외가 발생하더라도 프로그램을 종료시키지 않고 계속해서 프로그램을 실행할 수 있다. 다음 그림은 try~catch문의 기본 사용법을 나타낸다.
try{ // x1, 예외 객체가 발생하는 부분 } catch(ArithmeticException ae){ // x2, 예외 잡기 // x3, 여기서 처리 } |
x1행을 시도(try)해보고 예외가 발생하면 x2행에서 이 예외 객체를 잡아서(catch) x3행에서 적절한 처리를 한다. 예외 객체를 잡는다는 것은 ae가 예외 객체를 참조한다는 것이다. ae가 예외 객체를 참조하기 때문에 x3행에서 예외 객체에 대한 어떤 처리를 할 수 있다. 그런데 ae가 잡을 수 있는 예외는 ArithmeticException형 객체이다. 따라는 다른 종류의 예외가 발생하면 x2행에서 잡지 못한다.
Excep2.java |
|
public class Excep2{
public static void main(String[] args){
System.out.println("프로그램 시작");
int a=1,b=0;
try{
int c=a/b; // x1, 여기서 예외 객체 생김
System.out.println(c); // x2
}catch(ArithmeticException ae){ // x3
System.out.println("0으로 나누면 안되지~잉"); // x4
}
System.out.println("프로그램 종료"); // x5
}
}
출력 결과 |
|
프로그램 시작
0으로 나누면 안되지~잉
프로그램 종료
x1행에서 예외(ArithmeticException)가 발생한다. x3행에서 이 예외를 잡아서 x4행에서 적절한 예외 처리를 수행한다. x5행을 실행하고 프로그램이 정상적으로 종료된다. x1행에서 예외가 발생하였으므로 x2행은 실행되지 않고 catch문으로 넘어 간다는 것에 주의하자. x1행에서 ArithmeticException 예외가 아닌 다른 예외가 발생하면 x3행에서 이 예외를 처리하지 않는다.
NullPointerException은 레퍼런스가 null을 참조할 때 발생하는 예외이다. null을 참조한다는 것은 레퍼런스가 어떤 객체도 참조하지 않는다는 것을 독자는 이미 알고 있을 것이다. 참조하는 객체가 없기 때문에 멤버도 역시 존재하지 않는다.
Excep3 ob=null; ob.hi(); // NullPointerException 발생 |
다음 예제는 NullPointerException이 발생했을 때 예외 처리를 하는 예제이다.
Excep3.java |
|
public class Excep3{
void hi(){
System.out.println("하이여~~");
}
public static void main(String[] args){
Excep3 ob=null;
try{
ob.hi(); // NullPointerException 발생
}catch(NullPointerException ne){
ob=new Excep3(); // 객체 할당
}
ob.hi(); // 여기서 출력
}
}
출력 결과 |
|
하이여~~
여러 종류의 예외를 처리하고자 할 경우에는 catch를 중복해서 사용한다.
try{①} catch(ArithmeticException e){②} catch(NullPointerException e){③} catch(ArrayIndexOutOfBoundsException e){④} finally{⑤} |
finally는 try~catch문 맨 아래쪽에 작성하고, 예외 발생 유무와 상관없이 무조건 실행된다. finally는 생략할 수도 있으며 무조건 실행해야할 명령이 있을 때 사용하면 된다. 위 코드의 실행 순서는 다음과 같다.
①에서 ArithmeticException가 발생하면 ②, ⑤를 실행한다.
①에서 NullPointerException이 발생하면 ③, ⑤를 실행한다.
①에서 ArrayIndexOutOfBoundsException이 발생하면 ④, ⑤를 실행한다.
알아두기 |
|
ArrayIndexOutOfBoundsException 배열(Array)의 원소 번호(index)가 범위(bounds)를 넘었을 때 발생하는 예외이다.
int[] a = new int[5]; // a[0], a[1], a[2], a[3], a[4] a[10] = 200; // a[10]은 존재하지 않음, 예외 발생 |
Excep4.java |
|
public class Excep4{
public static void main(String[] args){
int[] a=new int[5];
try{
a[10]=200; // x1, ArrayIndexOutOfBoundsException
}catch(ArithmeticException e){
System.out.println(e);
}catch(NullPointerException e){
System.out.println(e);
}catch(ArrayIndexOutOfBoundsException e){ // x2
System.out.println(e); // x3
}finally{
System.out.println("무조건 실행"); // x4
}
}
}
출력 결과 |
|
java.lang.ArrayIndexOutOfBoundsException
무조건 실행
x1행에서 ArrayIndexOutOfBoundsException이 발생한다.
x2행에서 ArrayIndexOutOfBoundsException을 잡고 x3행을 실행한다.
x4행은 무조건 실행된다.
혼자 해보기 |
Alone11_1.java |
다음 소스를 컴파일 하면 어떤 예외가 발생하는가?
public class Alone11_1{
public static void main(String[] args){
int[] a;
a[10]=100;
}
}
Exception의 종류
앞에서 다룬 예외 말고도 많은 예외가 존재하고 상속 관계가 있다. 예외를 다루는 클래스들의 최상위 클래스는 Throwable이고 이를 상속하는 클래스는 각각 Exception과 Error이다. Error는 메모리가 부족하다든지 하는 치명적인 에러인데 처리하고 싶어도 별 뾰족한 수가 없으므로 다루지 않는다. 반면에 Exception은 try~catch로 잡을 수 있는 작은 에러이다.
[그림 11-1] Exception 계층도
Throwable은 '던질 수 있는'의 뜻인데 왜 그런 이름을 가지게 되었는지는 나중에 알게 될 것이다.
프로그램을 짤 때 자주 발생되는 예외는 RuntimeException이고 이 예외가 발생하는 대부분의 이유는 코딩을 잘못했기 때문이다. 앞으로 프로그램을 짜다가 이 예외가 발생하면 해당 코드를 올바르게 수정하자. 하지만 때에 따라 try~catch문을 사용해야만 하는 경우도 있다. RuntimeException은 Exception을 상속한다.
RuntimeException의 종류 |
설명 |
ArithmeticException |
수학적 예외, 예) 0으로 나눔 |
NullPointerException |
레퍼런스가 null을 참조할 때 발생 |
ArrayIndexOutOfBoundsException |
배열의 범위를 초과할 때 |
NegativeArraySizeException |
배열의 크기가 음(-)일 때 |
ArrayStoreException |
배열에 대입하는 값이 올바르지 않을 때 |
IllegalArgumentException |
매개 변수에 잘못된 값이 대입될 때 |
SecurityException |
보안상의 예외 |
[표 11-1] RuntimeException의 종류
부모 레퍼런스는 모든 자식 객체를 참조할 수 있다. 따라서 모든 예외 객체의 부모인 Exception 레퍼런스는 모든 예외 객체를 참조할 수 있다. 같은 말로 Exception 레퍼런스는 모든 예외를 잡을 수 있다.
Excep5.java |
|
public class Excep5{
public static void main(String[] args){
try{
int[] a=new int[-1]; // NegativeArraySizeException 발생
}catch(Exception e){ // e는 모든 예외를 잡을 수 있다.
System.out.println(e);
}
}
}
출력 결과 |
|
java.lang.NegativeArraySizeException
예외를 던지는 메소드
어떤 메소드는 호출했을 때 예외를 발생시킬 수 있는데, 그런 메소드를 예외를 던지는 메소드라고 부른다. 다음 코드에서 go가 예외를 던지는 메소드이다.
static void go() throws NegativeArraySizeException{ int[] a=new int[-1]; // x1 } // 'throws'는 말 그대로 '던지다'의 의미이다. |
예외를 try~catch로 처리할 수도 있지만 위와 같이 'throws'를 사용하여 예외를 처리할 수도 있다. go을 호출하여 실행하면 x1행에서 예외가 발생하는데 go를 호출한 곳으로 발생한 예외 객체를 던진다. 예제를 보면 쉽게 이해할 수 있을 것이다.
Excep6.java |
|
public class Excep6{
static void go() throws NegativeArraySizeException{
int[] a=new int[-1]; // x1
}
public static void main(String[] args){
try{
go(); // x2, 여기로 예외를 던진다.
}catch(NegativeArraySizeException e){ // x3
System.out.println("go가 예외를 던진다.");
}
}
}
출력 결과 |
|
go가 예외를 던진다.
x2행의 go를 호출하면 x1행을 실행하다가 예외가 발생한다. go는 예외를 던지는 메소드이므로 자기를 호출한 곳, 즉 x2행으로 예외 객체를 던진다. 진짜 예외는 x1행에서 발생하였지만 x2행으로 던졌기 때문에 x2행에서 예외가 발생하는 것이다. 증거로 x3행에서 예외가 잡히고 있다.
날라 온 예외 객체를 또 던질 수 있다. 얼마든지 던질 수 있다. 나중에 잘 잡으면 되니까.
Excep7.java |
|
public class Excep7{
static void go() throws NegativeArraySizeException{
int[] a=new int[-1]; // x1
}
static void hi() throws NegativeArraySizeException{
go(); // x2
}
public static void main(String[] args){
try{
hi(); // x3, 여기로 예외 객체가 던져짐
}catch(NegativeArraySizeException e){
System.out.println("멀리서 날라 왔네..");
}
}
}
출력 결과 |
|
멀리서 날라 왔네..
x3행에서 hi를 호출하면 x2행에서 go를 호출하고 x1행에서 예외가 발생한다. 발생한 예외 객체를 x2행으로 던지고, x2행에 날라 온 예외 객체를 x3행으로 던진다. go나 hi는 예외를 던지는 메소드이기 때문이다.
예외를 던지는 메소드라고 해서 무조건 예외가 발생하는 것은 아니다. 예외를 던지는 메소드란 예외를 던질 가능성이 있는 메소드를 말하는 것이다. 예제를 보자.
Excep8.java |
|
public class Excep8{
static void go(int size) throws NegativeArraySizeException{
int[] a=new int[size]; // size가 음수일 때만 예외 발생
System.out.println(a.length);
}
public static void main(String[] args){
try{
go(10); // x1, 예외가 발생하지 않음
}catch(NegativeArraySizeException e){
System.out.println("배열의 크기는 양수");
}
}
}
출력 결과 |
|
10
출력 결과를 보면 예외가 발생하지 않았다. x1행에서 10대신에 음수를 대입하면 예외가 발생할 것이다. 실제로 해보길 바란다.
예외를 던지는 메소드는 반드시 예외 처리를 해야한다. 아니면 컴파일 에러가 발생한다. 다음 예제를 컴파일 해보자.
Excep9.java |
|
public class Excep9{
public static void main(String[] args){
int a=0;
System.out.print("문자를 누르세요>> ");
// System.in.read()는 IOException을 던지는 메소드이다.
a=System.in.read(); // x1
System.out.println("누르신 문자는 "+ (char)a+"입니다.");
}
}
출력 결과 |
|
C:\...\Excep9.java:5: unreported exception java.io.IOException;
must be caught or declared to be thrown
a=System.in.read();
^
1 error
에러 메시지는 x1행에서 java.io.IOExcepion을 잡거나 던져야한다는 내용이다. x1행의 read()가 IOException을 던지는 메소드이므로 아래와 같이 예외 처리를 해야만 컴파일이 정상적으로 수행된다.
Excep10.java |
|
import java.io.IOException; // IOException을 import한다.
public class Excep10{
public static void main(String[] args){
int a=0;
System.out.print("문자를 누르세요>> ");
try{
a=System.in.read(); // x1
}catch(IOException e){
System.out.println("오류~~~~");
}
System.out.println("누르신 문자는 "+ (char)a+"입니다.");
}
}
출력 결과 |
|
문자를 누르세요>> A
누르신 문자는 A입니다.
read 메소드는 예외를 던지는 메소드로 정의되어 있다.
public abstract int read() throws IOException; |
따라서 예외 처리를 반드시 해야한다. 그러나 예제의 실행 결과처럼 예외를 던지지 않을 수도 있다. 참고로 read 메소드는 표준 입력 스트림(키보드)으로부터 1바이트를 읽어오는 메소드이다. 나중에 입출력 부분에서 자세히 살펴보자.
알아두기 |
|
RuntimeException을 던지는 메소드 RuntimeException은 예외 처리를 하지 않아도 컴파일은 수행된다. |
혼자 해보기 |
Alone11_2.java |
키보드로부터 한 문자를 입력받아 문자에 해당하는 ASCII를 출력하는 프로그램을 만들어보자.
※ System.in.read()는 1byte를 읽어서 int로 반환한다.
출력 결과 예시 |
|
문자: A ??
ASCII: 65
문자: b ??
ASCII: 98
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
[자바/SCJP/JAVA]내부 클래스(Inner Class)
클래스 안에 클래스를 정의할 수도 있는데 이런 클래스를 내부 클래스(Inner Class)라고 한다. 네 종류의 내부 클래스가 있다.
종류 |
형태 |
정적 클래스(Static Calss) |
클래스의 멤버로 static 클래스가 있는 경우 |
멤버 클래스(Member Class) |
클래스의 멤버로 클래스가 있는 경우 |
지역 클래스(Local Class) |
메소드 내에 클래스가 있는 경우 |
익명 클래스(Anonymous Class) |
이름이 없는 클래스 |
[표 10-1] 내부 클래스
정적 클래스(Static Calss)
static 클래스는 static 변수와 static 메소드의 이해 없이는 상당히 어려울 것이다. 독자가 생각하기에 static에 대한 이해가 부족하다고 생각되면 5장을 한번 더 보는 것도 좋을 것이다.
static 클래스를 다른 말로 중첩 클래스(Nested Class)라고 한다. 대부분의 자바 책에서 그렇게 부르고 있다. 하지만 필자의 경험으로 중첩이라는 말 자체도 어려웠고 static 클래스와 결부시켜 이해하는 것도 어려웠기 때문에 그냥 있는 그대로 static 클래스라고 부를 것이다.
짚어두기 |
|
static과 dynamic 영어 사전에서 찾아보면 각각 '정적인', '동적인'이라는 말로 서로 반대 말이다. static 변수는 메모리에 한번 자리를 잡으면 프로그램이 끝나기 전까지 결코 사라지지 않는다. 즉 static 변수는 정적(靜的)이다. 하지만 멤버 변수는 객체가 생성되면 생겼다가 객체가 소멸될 때 사라진다. 즉 일반 멤버 변수는 동적(動的)이다. |
다음 코드를 보면 클래스 내부에 static 클래스가 존재한다.
class Outer{ static class Inner{ } } |
Outer 클래스 안에 Inner 클래스가 있다. 이놈들을 어떻게 해석을 해야할까? Inner는 Outer안에 있으므로 Outer의 멤버라고 생각하자. 근데 Inner는 static 클래스이므로 static 멤버이다. static 멤버는 객체를 만들지 않고도 사용할 수 있으므로 Outer의 객체 없이도 Inner를 참조할 수 있다. 다른 말로 Outer의 객체 없이도 Inner의 객체를 만들 수 있다. Outer 클래스 외부에서 Inner 객체를 만들면 아래와 같다.
Outer.Inner ob=new Outer.Inner(); |
static 변수를 클래스 외부에서 참조하는 것과 비슷해 보인다.
Outer 클래스 내부에서 Inner 객체를 만들면 아래와 같다.
Inner ob=new Inner(); |
클래스 내부에서 Inner를 참조하기 때문에 클래스이름을 생략해도 된다.
static 메소드에서 static 변수나 메소드를 참조할 수 있는 것과 같이 static 클래스인 Inner도 Outer의 static 변수나 메소드를 참조할 수 있다. 하지만 일반 멤버는 참조할 수 없다.
class Outer{ static int a=10; int b=20; static void f(){...} static class Inner{ void g(){ int d=a; // static 변수 f(); // static 메소드 // b=100; 일반 멤버는 참조 불가 } } } |
이제 예제를 보고 분석해 보자.
Static1.java |
|
class Outer{
static int a=10;
int b=20;
static void f(){
System.out.println("hi~~");
}
static class Inner{
int c=30;
public void g(){
f(); // Outer의 static 메소드 호출
System.out.println(a+" "+c); // Outer의 static 변수 참조
}
}
}
public class Static1{
public static void main(String[] args){
Outer.Inner ob=new Outer.Inner();
ob.g();
}
}
출력 결과 |
|
hi~~
10 30
위 예제와 같이 static 클래스는 Outer의 멤버지만 Outer의 객체 없이도 Inner 클래스의 객체를 만들 수 있다.
멤버 클래스(Member Class)
멤버 클래스의 모양은 다음과 같다.
class Outer{ class Inner{ } } |
Inner가 Outer의 멤버로 정의된 경우이다. 객체를 만들어야만 멤버 변수를 사용할 수 있는 것과 같이, Outer의 객체가 있어야 Inner의 객체를 만들 수 있다.
Outer out=new Outer(); // Outer의 객체 Outer.Inner in=out.new Inner(); // Inner의 객체는 Outer의 객체를 통해서 |
모양이 이상하다. 하지만 곰곰이 생각해보면 이해될 것이다.
멤버 메소드에서 모든 멤버를 참조할 수 있듯이, Inner 클래스는 Outer의 모든 멤버를 참조할 수 있다.
class Outer{ static int a=10; int b=20; static void f(){...} void g(){...} class Inner{ void h(){ int d=a; // static 변수 f(); // static 메소드 b=100; // 멤버 변수 g(); // 멤버 메소드 } } } |
아래 예제를 실행해보고 분석해 보자.
Member1.java |
|
class Outer{
static int a=10;
int b=20;
void f(){
System.out.println("hi~~");
}
class Inner{
int c=30;
public void g(){
b=100;
f();
System.out.println(a+" "+c);
}
}
}
public class Member1{
public static void main(String[] args){
Outer out=new Outer();
Outer.Inner in=out.new Inner();
in.g();
System.out.println(out.b);
}
}
출력 결과 |
|
hi~~
10 30
100
Outer 클래스의 멤버 메소드에서 Inner 클래스의 객체를 만들 수도 있다. 이 때는 Outer의 객체가 이미 만들어진 상태이므로 다음 예제의 x1행과 같이 하면 된다.
Member2.java |
|
class Outer{
void f(){
Inner in=new Inner(); // x1, 이미 Outer의 객체가 만들어졌다.
System.out.println(in.a);
}
class Inner{
int a=100;
}
}
public class Member2{
public static void main(String[] args){
Outer out=new Outer(); // 여기서 Outer의 객체가 만들어짐.
out.f();
}
}
출력 결과 |
|
100
외부 클래스의 객체가 있어야만 멤버 클래스를 참조할 수 있기 때문에 멤버 클래스 내의 멤버는 static이 될 수 없다. 하지만 상수는 가능하다.
class Outer{ class Inner{ int a; // 가능 void f(){...} // 가능 static final int b=10; // 가능 static int c; // 에러 static void g(){...} // 에러 } } |
다음 코드와 같이 Outer 클래스의 멤버와 Inner 클래스의 멤버의 이름이 같은 경우가 있다.
class Outer{ int a; // x1 class Inner{ static final int a=20; // x2 void f(){ int b=a; // x3 int c=this.a // x4 int d=Outer.this.a // x5 } } } |
x3행이나 x4행의 a나 this.a는 x2행의 a를 가리킨다. 외부클래스의 멤버를 참조하려면 x5행과 같이 한다. Outer.this는 Outer의 객체의 레퍼런스이다. Outer 객체의 this와 Inner 객체의 this를 구분하기 위하여 위와 같이 하는 것이다.
다음 예제로 확인해보자.
Member3.java |
|
class Outer{
int a=10; // x1
class Inner{
static final int a=100; // x2
void f(){
System.out.println(this.a); // this.a는 x2행의 a를 가리킴
System.out.println(Outer.this.a); // Outer.this.a는 x1행의 a를 가리킴
}
}
}
public class Member3{
public static void main(String[] args){
Outer out=new Outer();
Outer.Inner in=out.new Inner();
in.f();
}
}
출력 결과 |
|
100
10
지역 클래스(Local Class)
지역 클래스는 지역 변수와 같이 메소드 내부에서 정의된 클래스이다.
void f(){ class Inner{ } } |
메소드 f() 내부에 Inner 클래스가 정의되어 있다. 정말이지 묘한 모양을 하고 있다. 하지만 지역 변수와 같다고 생각하면 된다. 지역 변수는 메소드 내부에서만 사용할 수 있고 메소드의 실행이 끝나면 사라진다. 지역 클래스도 마찬가지로 메소드 내부에서만 객체를 만들 수 있고 메소드의 실행이 끝나면 클래스가 메모리에서 사라진다.
void f(){ class Inner{ // x1 void hi(){ System.out.println("안뇽~~~"); } } Inner in=new Inner(); // x2, 메소드 내부에서 객체를 생성 in.hi(); // x3 } // x4 |
메소드 f()를 호출하면 x1행에서 Inner 클래스가 정의된다. x2행에서 객체를 만들고 사용한다. x4행에서 메소드 f()의 실행이 종료되면 메소드 내부에서 정의된 모든 것들이 소멸된다. 즉, Inner 클래스와 in의 객체가 메모리에서 제거된다. 메소드를 호출할 때마다 이 같은 과정이 반복된다.
지역 클래스는 자신을 포함하는 클래스(enclosing class)의 모든 멤버를 참조할 수 있다.
Local1.java |
|
public class Local1{
int a=10;
void f(){
class Inner{
int c=20;
void hi(){
System.out.println(a);
System.out.println(c);
}
}
Inner in=new Inner();
in.hi();
}
public static void main(String[] args){
Local1 local=new Local1();
local.f();
}
}
출력 결과 |
|
10
20
지역 클래스는 자신을 포함하는 메소드의 지역 변수나 매개 변수 중에 final만 참조할 수 있다.
다음 예제를 해보자.
Local2.java |
|
public class Local2{
void f(final int a, int b){
int c=30;
final int d=40;
class Inner{
void hi(){
System.out.println(a);
// System.out.println(b); 에러, final이 아니다.
// System.out.println(c); 에러
System.out.println(d);
}
}
Inner in=new Inner();
in.hi();
}
public static void main(String[] args){
Local2 local=new Local2();
local.f(10,20);
}
}
출력 결과 |
|
10
40
익명 클래스(Anonymous Class)
interface로 정의된 Inter가 다음과 같이 정의되어 있다고 가정하자.
interface Inter{ public void f(); } |
Inter를 구현하는 클래스를 만들고자 한다. 그런데 이 클래스로부터 단 하나의 객체가 만들어진다면 다음과 같이 할 수 있다.
Inter ob = new Inter(){★}; |
★가 있는 자리에 Inter를 구현하면 되는데, '{★}'를 익명 클래스(이름 없는 클래스)라고 한다. 이렇게 클래스를 정의하면 이 클래스는 레퍼런스 변수 ob만 사용할 수 있다.
Inter ob=new Inter(){ public void f(){ System.out.println("안녕~~~"); } }; // 세미콜론을 빼먹지 말자. |
위 코드를 가만히 보자. 클래스를 정의하고 객체를 만들지만 마치 객체를 정의하는 것처럼 보인다. 익명 클래스는 오직 하나의 객체를 위해서 정의하는 것이다.
다음 예제를 보고 분석해보자.
Anony1.java |
|
interface Inter{
public void hi();
}
public class Anony1{
public static void main(String[] args){
Inter ob1=new Inter(){ // Inner를 구현하는 객체를 생성한다.
public void hi(){
System.out.println("안녕~~~");
}
};
Inter ob2=new Inter(){ // Inner를 구현하는 객체를 생성한다.
public void hi(){
System.out.println("hello~~~");
}
};
ob1.hi();
ob2.hi();
}
}
출력 결과 |
|
안녕~~~
hello~~~
이름을 가진 클래스를 정의하는 것보다 익명 클래스를 사용하는 것이 코드가 적다.
인터페이스뿐만 아니라 클래스를 상속하는 익명 클래스도 만들 수 있다.
Anony2.java |
|
class Anony2_1{
public void hi(){
System.out.println("hi?");
}
public void hello(){
System.out.println("hello?");
}
}
public class Anony2{
public static void main(String[] args){
Anony2_1 ob=new Anony2_1(){ // Anony2_1을 상속하는 클래스의 객체
public void hi(){
System.out.println("안녕?");
}
};
ob.hi();
ob.hello();
}
}
출력 결과 |
|
안녕?
hello?
|
연습 문제 |
|
1. static 클래스와 멤버 클래스의 차이점은 무엇인가?
2. 멤버 클래스를 이용하는 목적이 무엇인지 생각해보자.
3. 익명 클래스의 장점은 무엇인가?
4. 다음의 Shape(도형) 인터페이스를 구현하는 클래스의 객체를 만들되 익명 클래스로 작성해보자.
public Interface Shape{
// 좌표(x, y)가 도형 내부에 있는 점이면 true를, 아니면 false를 반환한다.
public boolean contains(int x, int y);
// 영역(x, y, w, h)가 도형과 교차하면 true를 아니면 false를 반환한다.
// 영역이란 외쪽 상단의 좌표가 (x, y)이고 너비가 w, 높이가 h인 사각형이다.
public boolean intersects(double x, double y, double w, double h);
}
// 익명 클래스를 이용한 Shape 객체 만들기
Shape 사각형 = new Shape(){
...
};
Shape 원 = new Shape(){
...
};
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
[자바자격증/SCJP]
JSP로 한글처리를 위하여 페이지 상단에 <%@ page contentType="text/html; charset=euc-kr" %>
위와 같이 써주고 페이지에서 넘어온 Request값은 다음과 같이 받습니다.
<%
String strName = new String(request.getParameter("sName").getBytes("ISO-8859-1"),"euc-kr");
%>
이 넘어온 값이 Post가 아닌 Get방식으로 넘어왔을때 한글값이 깨진다.. 이럴때는 톰캣 Conf폴더의 server.xml 파일을
열고 아래 보이시는 빨간색 부분을 추가해 주세요.
<Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="MS949" />
출처 http://cafe.naver.com/edcxswqaz
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
출처 : MCSE,CCNA/CCNP,자바등 국제자격증 카페 http://cafe.naver.com/qlkdjlkanv
광고 | |||
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
출처 : MCSE,CCNA/CCNP,자바등 국제자격증 카페 http://cafe.naver.com/qlkdjlkanvabsolute;z-index:20'>
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
출처 : MCSE,CCNA/CCNP,자바등 국제자격증 카페 http://cafe.naver.com/qlkdjlkanvabsolute;z-index:20'>
▲구글이 공개한 '안드로이드' 기반 휴대폰 샘플 / 구글 본사 제공 |
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
출처 : MCSE,CCNA/CCNP,자바등 국제자격증 카페 http://cafe.naver.com/qlkdjlkanvabsolute;z-index:20'>
구글 '안드로이드' 개발 동작샘플 / 구글 본사 제공 |
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍
출처 : MCSE,CCNA/CCNP,자바등 국제자격증 카페 http://cafe.naver.com/qlkdjlkanv
광고 | |||
자바 자바학원 java java학원 scjp scjp학원 자바자격증 java자격증 scjp자격증 jsp ejb 자바프로그래밍 웹프로그래밍