20180716

국비교육/예제파일 2018. 7. 16. 21:01

'java > 예제파일' 카테고리의 다른 글

180713  (0) 2018.07.13
0712  (0) 2018.07.12
0627~0705  (0) 2018.07.09
180627~180629 예제파일  (0) 2018.06.29
Posted by Hearthole
,

180713

국비교육/예제파일 2018. 7. 13. 21:02

'java > 예제파일' 카테고리의 다른 글

20180716  (0) 2018.07.16
0712  (0) 2018.07.12
0627~0705  (0) 2018.07.09
180627~180629 예제파일  (0) 2018.06.29
Posted by Hearthole
,

0712

국비교육/예제파일 2018. 7. 12. 21:01

Bingo.java

y180712.zip


package bingoEx1;


import java.awt.Button;

import java.awt.Color;

import java.awt.Frame;

import java.awt.GridLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;


public class Bingo {

static String[][] bird = new String[][]{

{"참새","두루미","황새","비둘기","까오기"},

{"오리","타조","부엉이","올빼미","뱁새"},

{"꿩","닭","구관조","잉꼬","매"},

{"거위","독수리","콘돌","봉황","공작"},

{"까치","까마귀","앵무새","꾀꼬리","고니"}};

public static void main(String args[]) {

Frame f = new Frame("GridLayoutTest");

Button[][] b = new Button[5][5];

 // 버튼에 저장될 스트링

EventHandler e = new EventHandler();

f.setSize(500, 500);

f.setLayout(new GridLayout(5, 5)); // 5행 5열의 테이블을 만든다.

for(int i=0;i<5;i++) {

for(int j=0;j<5;j++) {

b[i][j] = new Button(bird[i][j]);

b[i][j].addActionListener(e); // 빙고의 행렬값 매개변수로 보냄 

f.add(b[i][j]);

}

}

f.setVisible(true);

}


}

class EventHandler implements ActionListener{

int cX = 0;

int cY = 0;

int cS = 0;

int cRS= 0;

int countB = 0; //빙고갯수카운트

int[][] bingo = new int[5][5]; //빙고게임기록용

public void actionPerformed(ActionEvent e) {

int i =0; // bingoCount로 보낼 행 매개변수로 사용

int j =0; // bingoCount로 보낼 열 매개변수로 사용

Button b = (Button)e.getSource(); // 소스이용한 임시 버튼생성

equals:

for(i=0;i<5;i++) { 

for(j=0;j<5;j++) {

if(Bingo.bird[i][j].equals(b.getLabel())) //문자열 배열값과  버튼 라벨값을 비교

break equals; // 맞는 배열 찾으면 중첩for문 빠져나감

}

}

System.out.println("버튼이름 = "+b.getLabel());

b.setBackground(Color.LIGHT_GRAY);

bingoCount(i,j); // i,j매개변수로 bingoCount실행

}

public void bingoCount(int x,int y) {

System.out.println("x="+x+", y="+y+", bingo[0][0]="+bingo[0][0]);

if(bingo[x][y]==0) { // 이미 클릭된 버튼인지 판단

bingo[x][y]=1;

for(int i=0;i<5;i++) {

for(int j=0;j<5;j++) {

if(bingo[i][j]==1) { // 버튼활성화여부

if(i==j) // 역슬래쉬카운트

cRS++;

if(i+j==4)  // 슬래쉬카운트

cS++;

cX++; //행빙고카운트

if(bingo[j][i]==1) 

cY++; //열빙고카운트 j , i 역순

if(cS==5)  {countB++; cS=0;} // 각 줄 5카운트시 빙고카운트1추가 후 변수 초기화

if(cX==5)  {countB++; cX=0;}

if(cY==5)  {countB++; cY=0;}

if(cRS==5) {countB++; cRS=0;}


} //for j 종료

cX=0;cY=0; //행렬카운트 초기화

} // for i 종료

cS=0; cRS=0; //슬래쉬카운트 초기화

System.out.println("현재 "+countB+"빙고!!");

countB=0; //빙고카운트 초기화

} else {

System.out.println(x+","+y+"번은 이미 체크되었습니다."); 

}



}// bingoCount 죵료

}



 



'java > 예제파일' 카테고리의 다른 글

20180716  (0) 2018.07.16
180713  (0) 2018.07.13
0627~0705  (0) 2018.07.09
180627~180629 예제파일  (0) 2018.06.29
Posted by Hearthole
,

2. 유용한 클래스


2-1 javja.util.Objects클래스

isNull()은 해당 객체가 널인지 확인해 null이면 true를, 아니면 false를 반환한다.

static boolean isNull(Object obj)


nonNull()은 반대의 역할을 한다.

static boolean nonNull(Object obj)


compare()는 두 비교대상이 같으면 0, 크면 양수, 작으면 음수를 반환한다.

static int compare(Object a, Object b, Comparator c)

이 메서드는 a,b두 객체를 비교하는데, 여기서 사용할 비교 기준이 c다.


equals()의 내부에서 a와 b가 같은지 비교한다. Object의 equals와 다른 점은 null검사를 하지 않아도 되는데 있다. a와 b가 모두 null인 경우 참을 반환한다.

static boolean equals(Object a, Object b)


deepEquals()는 객체를 재귀적으로 비교하기 때문에 다차원 배열의 비교도 가능하다.

String[][] str2D = new String[][]{{"aaa","bbb"},{"AAA","BBB"}};

String[][] str2D2 = new String[][]{{"aaa","bbb"},{"AAA","BBB"}};

System.out.println(Objects.equals(str2D, str2D2)); // false

System.out.println(Objects.deepEquals(str2D, str2D2));  // true

위와 같이 두 2차원 문자열 배열을 비교할 때, equals로는 반복문을 사용해야 했지만, deepEquals()로는 간단히 끝난다.


toString()도 equals처럼 내부적으로 널 검사를 하는 것 빼고는 같은 작용을 한다.


hashCode()도 내부적으로 널 검사를 한 후에 Object클래스의 hashCode()를 호출할 뿐이다. 널일 떄는 0을 반환한다.

static int hashCode(Object o)

static int hash(object.. values)


Objects와 Object의 메서드중 이름이 같은 것들은 컴파일러가 구분을 못하므로 충돌이 난다. 

클래스 이름을 붙여주도록 하자.


2-2 java.util.random클래스

int num = (int)(Math.random()*6) + 1;

int num = new Random().nextInt(6) + 1; // nextInt(6)은 0~6사이의 정수를 반환

Random은 Math.random()과 다르게 종자값(seed)를 설정할 수 있다. 종자값이 같은 랜덤 인스턴스들은 항상 같은 난수를 같은 순서대로 반환한다. 


Random클래스의 생성자와 메서드

p.500 참조


스캐너,토크나이저,빅

Posted by Hearthole
,

1. java.lang패키지

 

1-1 Object클래스

Object클래스는 모든 클래스의 최고조상이기 때문에 Object클래스의 멤버들은 모든 클래스에서 바로 사용 가능하다.

 Object클래스의 메서드  설     명
 protected Object clone() 객체 자신의 복사본을 반환한다. 
public boolean equals (Object obj)  객체 자신과 obj가 같은 객체인지 알려준다. (같으면 true) 
 protected void finalize() 객체가 소멸될 때 가비지 컬렉터에 의해 자동적으로 호출된다. 이 때 수행되어야하는 코드가 있을 때 오버라이딩 한다. (거의 사용 안함) 
 public Class get Class() 객체 자신의 클래스 정보를 담고 있는 Class인스턴스를 반환한다. 
public int hashCode()  객체 자신의 해시코드를 반환한다. 
public void notify()  객체 자신을 사용하려고 기다리는 쓰레드를 하나만 깨운다. 
public void notifyAll()  객체 자신을 사용하려고 기다리는 모든 쓰레드를 깨운다. 
 public String toString() 객체 자신의 정보를 문자열로 저장한다. 
public void wait()
public void wait(long timeout)
public void wait(long timeout, int nanos) 
 다른 쓰레드가 notify()나 notifyAll()을 호출할 때까지 현제 쓰레드를 무한히 또는 지정된 시간(time out, nanos)동안 기다리게 한다. (timeout은 천 분의 1초, nanos는 10^9분의 1초)

 

Object클래스는 멤버변수는 없고 오직 11개의 메서드만 가지고 있다.

 

얕은 복사와 깊은 복사

clone()은 단순히 객체에 저장된 값을 그대로 복제할 뿐, 객체가 참조하고 있는 객체까지 복제하지는 않는다. 이를 완전한 복제라고 보기는 어려우므로 이러한 복제를 '얕은 복사(shallow copy)'라고 한다. 얕은 복사에서는 원본을 변경하면 복사본도 영향을 받는다.

 반면에 원본히 참조하고 있는 객체까지 복제하는 것을 '깊은 복사(deep copy)'라고 하며, 깊은 복사에서는 원본과 복사본이 서로 다른 객체를 참조하기 때문에 원본의 변경이 복사본에 영향을 미치지 않는다.

 

 

1-2 String클래스

 

변경불가능한(immutable) 클래스

한번 생성된 String 인스턴스가 갖고 있는 문자열은 읽어 올 수만 있고, 변경할 수는 없다.

문자열간의 결합이나 추출 등 문자열을 다루는 작업이 많이 필요한 경우에는 String클래스 대신 StringBuffer클래스를 사용하는 것이 좋다.

 

문자열의 비교 

문자열을 만들 때눈 두 가지 방법 문자열 리터럴을 지정하는 방법과 String클래스의 생성자를 사용해서 만드는 방법이 있다.

 

String str1 = "abc"; // "abc"의 주소가 str1에 저장됨. (이미 존재하는 것 재사용)

String str2 = new String("abc"); // 새로운 String인스턴스를 생성 (새 메모리 할당)

 

문자열 리터럴

자바 소스파일에 포함된 모든 문자열 리터럴은 컴파일 시에 클래스 파일에 저장된다. 이때 같은 내용의 문자열 리터럴은 한번만 저장된다. 문자열 리터럴도 String인스턴스이고, 한번 생성하면 내용을 변경할 수 없으니 하나의 인스턴스를 공유하면 되기 때문이다.

 

빈 문자열(empty string)

길이가 0인 배열도 존재 할 수 있다.

 

String s =""; // 빈 문자열로 초기화

char c = ' '; // 공백으로 초기화 

 

String클래스의 생성자와 메서드

p.468 참고

 

join()과 StringJoiner

join()은 여러 문자열 사이에 구분자를 넣어 결합한다. 구분자로 문자열을 자르는 split()와 반대의 작업을 한다.

String animals = "dog,cat,bear";

String[] arr = animals.split(","); // 문자열을 ','구분자로 나눠서 배열에 저장

String str = String.join("-",arr); // 배열의 문자열을 '-'로 구분해서 결합

System.out.println(arr); // dog-cat-bear

 

String.format()

printf()와 사용법이 완전히 같다.

 

기본형 값을 String 문자열로 변환

간단히 숫자에 빈문자열 ""을 더해주면 된다. 이 외에 valueOf()를 사용하는 방법도 있다. 성능은 이쪽이 더 좋으나 방법은 전자가 더 간단하기에 성능향상이 필요한 경우에만 사용하자.

 

int i = 100;

String str1 = i+"";

String str2 = String.valueOf(i);

 

String을 기본형 값으로 변환

valueOf()를 쓰거나 parseInt()를 사용하면 된다.

int i = Integer.parseInt("100"); 

int i2 = Integer.valueOf("100");

실제로 valueOf()의 반환타입은 int가 아닌 integer이지만, 이는 오토박싱에 의해 자동 변환된다.

 

 

1-3 String클래스와 StringBuilder클래스

String클래스는 인스턴스를 생성할 때 지정된 문자열을 변경할 수 없지만 StringBuffer클래스는 변경이 가능하다.

 

StringBuffer의 생성자

StringBuffer클래스의 인스턴스를 생성할 때, 적절한 길이의 char형 배열이 생성되고, 이 배열이 문자열을 저장하고 편집하기 위한 공간(Buffer)로 사용된다.

크기를 별도로 지정하지 않으면 버퍼의 크기는 16이 된다.

 

StringBuffer의 변경

String과 달리 StringBuffer는 자신의 주소를 반환한다.

append()는 반환타입이 StringBuffer인데 자신의 주소를 반환한다. 아래와 같은 문장이 수행되면 sb에 새로운 문자열이 추가되고 sb자신의 주소를 반환하여 sb2에는 sb의 주소가 저장된다.

 

StringBuffer sb2 = sb.append("ZZ"); // sb의 내용뒤에 "ZZ"를 반환한다.

System.out.println(sb); // abc123ZZ

System.out.println(sb2); // abc123ZZ

 

sb와 sb2가 모두 같은 StringBuffer인스턴스를 가리키고 있으므로 같은 내용이 출력된다.

 

sb.append("123").append("ZZ");

따라서 이러한 표현도 가능하다. 밑줄 친 부분이 sb이기 때문이다.

 

StringBuffer의 비교

String클래스에서는 equals메서드를 오버라이딩해서 문자열의 내용을 비교하도록 되어있지만, StringBuffer클래스는 그렇지 않아서 StringBuffer클래스의 equals를 사용해도 등가비교연산자(==)로 비교한것과 같은 결과를 얻는다.

반면에 toString()은 오버라이딩되어 있어서 StringBuffer인스턴스에 toString()을 호출하면, 담고있는 문자열을 String으로 반환한다. 따라서 StringBuffer인스턴스의 문자열 비교를 위해서는 toString()을 호출해서 String인스턴스를 얻은 후, 두 값을 equals메서드로 비교해야한다. 

 

String s = sb.toString();

String s2 = sb2.toString();

 

System.out.println(s.equals(s2)); // true출력

 

StringBuffer클래스의 생성자와 메서드

p.480 참조

 

StringBuilder란?

StringBuffer클래스는 멀티쓰레드에 안전하도록 동기화되어 있는데, 멀티쓰레드로 작성된 프로그램이 아닌 경우, 동기화는 불필요하게 성능만 떨어뜨린다.

StringBuilder는 StringBuffer에서 동기화 기능만만 뺀 클래스이며, 나머지 기능은 모두 같다. 

 

 

1-4 Math클래스

Math클래스는 기본적인 수학계산에 유용한 메서드로 구성되어 있다.

 

올림, 버림, 반올림

소수점 n번째 자리에서 반올림한 값을 얻기 위해서는 round()를 사용해야 하는데, 이 메서드는 항상 소수점 첫째자리에서 반올림해서 정수값(long)을 돌려준다.

 원하는 자리 수에서 반올림된 값을 얻기 위해서는 간단히 10의 n제곱으로 곱한 후 다시 곱한 수로 나눠주기만 하면 된다.

 

1. 원래 값에 100을 곱한다.

90.7552*100 -> 9075.52

2. 위의 결과에 Math.round()를 사용한다.

Math.round(9075.52) -> 9076

3. 위의 결과를 다시 100.0으로 나눈다.

9076 / 100.0 -> 90.76

9076 / 100 -> 90 // 정수형 계산에서는 반올림이 이루어지지 않음.

 

짝수 반올림

rint()는 짝수반올림 메서드인데, 주로 반올림 오차를 줄이는데 이용한다.

 

예외를 발생시키는 메서드

메서드 이름에 'Exact'가 포함된 메서드들이 JDK1.8부터 추가되었다. 이들은 정수형 연산에서 발생할수 있는 오버플로우(overflow)를 감지하기 위한 것이다.

연산자는 단지 결과를 반환할 뿐, 오버플로우의 발생여부에 대해 알려주지 않는데, 위의 메서드들은 오버플로우가 발생하면 예외를 발생시킨다.

 

삼각함수와 지수,로그

자세한 내용은 JavaAPI 참조.

 

StrictMath클래스

OS별로 계산값이 다를수 있는 Math클래스의 대안으로 작성되었다. 다만 성능은 다소 떨어진다.

 

Math클래스의 메서드

 p.489 참조

 

 

1-5 래퍼(wrapper) 클래스

객체지향 개념에서 모든 것은 객체로 다루어져야 한다. 그러나 자바에서는 8개의 기본형을 객체로 다루지 않는다. 

 다만, 때로는 기본형(primitive type) 변수도 어쩔 수 없이 객체로 다뤄야 할 때가 있는데, 예를 들면 매개변수로 객체를 요구할 때, 기본형 값이 아닌 객체로 저장해야할 때, 객체간의 비교가 필요할 때 등등의 경우에는 기본형 값들을 객체로 변환하여 작업을 수행해야 한다.

 이 때 사용되는 것이 래퍼(wrapper)클래스이다. 8개의 기본형을 대표하는 8개의 래퍼클래스가 있는데, 이 클래스들을 이용하면 기본형 값을 객체로 다룰 수 있다. 

 

boolean - Boolean

char - Character

byte - Byte

short - Short

int - Integer

long - Long

float - Float

double - Double

 

래퍼클레스의 생성자는 매개변수로 문자열이나 각 자료형의 값들을 인자로 받는다.

 

Number클래스

이 클래스는 추상클래스로 내부적으로 숫자를 멤버변수로 갖는 래퍼클래스들의 조상이다. 기본형 중에서 숫자와 관련된 래퍼클래스들은 모두 Number클래스의 자손이라는 것을 알 수 있다.

Number클래스의 자손으로 BigInteger와 BigDecimal 등이 있는데, BigInteger는 long으로도 다룰 수 없는 큰 범위의 정수를, BigDecimal은 double로도 다룰 수 없는 큰 범위의 부동 소수점수를 처리하는데 사용한다.

 

문자열을 숫자로 변환하기

 

기본형 반환값

타입.parse타입(String s)

Integer.parseInt("100");

 

래퍼타입 반환값

타입.valueOf( )

Integer.valueOf("100");

 

16진법변환

Integer.parseInt("FF",16);

 

오토박싱 & 언박싱(autoboxing & unboxing)

JDK 1.5 이전에는 기본형과 참조형 간의 연산이 불가능해 래퍼클래스로 기본형을 객체로 만들어서 연산해야 했다. 그러나 이제는 기본형과 참조형의 덧셈이 가능하다. 자바 언어의 규칙이 바뀐 것은 아니고 컴파일러가 자동으로 변환코드를 넣어준다.

이처럼 기본형 값을 래퍼클래스의 객체로 자동변환하는 것을 오토박싱(autoboxing), 반대로 변환하는 것을 언박싱(unboxing)이라 한다.

 

 

Posted by Hearthole
,

1. 예외처리(exception handling)


1-1 프로그램 오류


컴파일 에러 - 컴파일 시에 발생하는 에러

런타임 에러 - 실행 시에 발생하는 에러

논리적 에러 - 실행은 되지만 의도와 다르게 동작하는 것


에러(error) - 프로그램 코드에 의해서 수습될 수 없는 심각한 오류

예외(exception) - 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류



1-2 예외 클래스의 계층구조


모든 예외의 최고 조상은 Exception 클래스이며, 상속계층도를 Exception클래스부터 도식화하면 다음과 같다.

Exception

└ IOException

└ ClassNotFoundException

└ ...

RuntimeException

└ ArtihmeticException

└ ClassCastException

└ ...

└ IndexOutOfBoundsException

Exception 클래스들 - 사용자의 실수와 같은 외적인 요인에 의해 발생하는 에외 (checked)

RuntimeException 클래스들 - 프로그래머의 실수로 발생되는 예외 (unchecked)



1-3 예외 처리하기 - try-catch문


예외처리(exception handling)의

정의 - 프로그램 실행 시 발생할 수 있는 예외의 발생에 대비한 코드를 작성하는 것

목적 - 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것


try-catch문의 구조

try{

//예외가 발생할 가능성이 있는 문장들

} catch (Exception1 e1) {

//예외 발생시 처리를 위한 문장

} catch (Exception2 e2) {

//처리 문장

}



1-4 try-catch문에서의 흐름


try블럭 내에서 예외가 발생한 경우

1.발생한 예외와 일치하는 catch블럭이 있는지 확인한다.

2.일치하는 catch블럭을 찾게 되면 그 catch블럭 내의 문장들을 수행하고 전체 try-catch문을 빠져나가 그 다음 문장을 계속 수행한다. 만일 일치하는 catch블럭을 찾지 못하면, 예외는 처리되지 못한다.


try블럭 내에서 예외가 발생하지 않은 경우

1.catch블럭을 거치지 않고 전체 try-catch문을 빠져나가서 수행을 계속한다.



1-5 예외의 발생과 catch블럭

모든 예외 클래스는 Exception클래스의 자손이므로, catch블록의 괄호()에 Exception클래스 타입의 참조변수를 선언해 놓으면 어떤 종류의 예외가 발생하더라도 이 catch블럭에 의해 처리된다.

만일 첫 번째 블럭에서 예외가 발생하면 두 번째 블럭은 검사하지 않게 된다.


printStackTrace()와 getMessage()

printStackTrace() - 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.

getMessage() - 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.


멀티 catch블럭

JDK 1.7부터 여러 catch 블럭을 ' | '기호를 이용해 하나의 catch블럭으로 합칠수 있게 되었으며, 이를 '멀티 catch블럭'이라 한다.

ex)

try{ ...

} catch (ExceptionA | ExceptionB e) {

e.printStackTrace();

}

만일 ' | ' 기호로 연결된 예외 클래스가 조상과 자손의 관계에 있다면 컴파일 에러가 발생한다. 

그러한 표현이 조상 하나만 써주는것과 다를 바 없기 때문이다.


1-6 예외 발생시키기

키워드 throw를 이용해 고의로 예외를 발생시킬 수 있으며, 방법은 아래의 순서를 따른다.

1. 먼저 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든 다음

Exception e = new Exception("고의로 발생시켰음");

2. 키워드 throw를 이용해서 예외를 발생시킨다.

throw e;



1-7 메서드에 예외 선언하기

예외를 처리하는 방법에는 try-catch문 외에 예외를 메서드에 선언하는 방법이 있다.

메서드에 예외를 선언하려면 메서드의 선언부에 키워드 throws를 사용한다. 여러개일 경우 쉼표로 구분한다.


void method() throws Exception1, Exception2, ... ExceptionN{

// 메서드의 내용

}


1-8 finally블럭


finally블럭은 try-catch문과 함께 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킨다.

try-catch-finally순서로 구성된다.


try { //예외 발생 가능성이 있는 문장

} catch (Exception1 e1) { //예외처리를 위한 문장

} finally { //예외의 발생여부에 상관없이 수행되어야만 하는 문장

}


1-9 자동자원 반환 -try-with-resouces문

jdk1.7부터 추가되었다. try-catch문의 변형이다.


1-10 사용자정의 예외 만들기

기존에 정의된 예외 클래스 외에 필요에 따라 새로운 예외 클래스를 정의하여 사용할 수 있다. 보통 Exception 클래스를 상속받지만, 필요에 따라 다른 예외 클래스도 선택할 수 있다.


1-11 예외 되던지기(exception re-throwing)

예외가 발생할 가능성이 있는 메서드에서 try-catch문을 사용해 예외를 처리해 주고 catch문에서 필요한 작업을 행한 후에 throw문을 사용해 예외를 다시 발생시킨다. 다시발생한 예외는 이 메서드를 호출한 메서드에게 전달되고 호출한 메서드의 try-catch문에서 예외를 또다시 처리한다.

 하나의 예외에 대해서 예외가 발생한 메서드,호출한 메서드 양쪽 모두에서 처리해줘야 할 작업이 있을때 사용된다.


1-12 연결된 예외(chaind exception)

한 예외가 다른 예외를 발생시킬 수도 있다. 예를 들어 예외 A가 예외 B를 발생시켰다면, A를 B의 '원인 예외(cause exception)'라고 한다.


Throwable initCause (Throwable cause) // 지정한 예외를 원인 예외로 등록

Throwable getCause ()                     // 원인 예외를 반환


RuntimeException (Throwable cause) // 원인예외를 등록하는 생성자




Posted by Hearthole
,

'java > 예제파일' 카테고리의 다른 글

20180716  (0) 2018.07.16
180713  (0) 2018.07.13
0712  (0) 2018.07.12
180627~180629 예제파일  (0) 2018.06.29
Posted by Hearthole
,

8. 내부 클래스(inner class)

클래스 내에 선언된다는 점을 제외하고는 일반적인 클래스와 다르지 않으며, 몇가지 특징만이 별도로 존재한다.


8-1 내부 클래스란?

내부 클래스는 클래스 내에 선언된 클래스이다. 두 클래스가 서로 긴밀한 관계에 있을 때 이렇게 선언할 것을 고려한다.


내부 클래스의 장점

-내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 잇다.

- 코드의 복잡성을 줄일 수 있다(캡슐화).


8-2 내부 클래스의 종류와 특징

내부 클래스의 종류는 변수의 선언위치에 따른 종류와 같다. 내부 클래스는 마치 변수를 선언하는 것과 같은 위치에 선언할 수 있으며, 변수의 선언위치에 따라 구분되는 것과 같이 내부 클래스도 다음과 같이 구분되어 진다. 여러모로 변수와 유사하다.


내부 클래스

특   징

인스턴스 클래스

(instance class)

 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 인스턴스 멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언된다.

스태틱 클래스

(static class) 

 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static메서드에서 사용될 목적으로 선언된다.

 지역 클래스

(local class)

 외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다.

 익명 클래스

(anoymous class)

 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스 (일회용)


8-3 내부 클래스의 선언

변수가 선언된 위치에 따라 타입이 나뉘듯이 내부 클래스도 이와 마찬가지로 선언된 위치에 따라 나뉜다.


8-4 내부 클래스의 제어자와 접근성

인스턴스클래스와 스태틱 클래스는 외부 클래스와 멤버변수(인스턴스변수와 클래스변수)와 같은 위치에 선언되며, 또한 멤버변수와 같은 성질을 갖는다. 따라서 내부 클래스가 외부 클래스의 멤버와 같이 간주되고, 인스턴스멤버와 static멤버 간의 규칙이 내부 클래스에도 똑같이 적용된다. 그리고 내부 클래스도 클래스이기 때문에 abstract나 final과 같은 제어자를 사용할 수 있을 뿐만 아니라, 멤버변수들처럼 private, protected와 접근제어자도 사용이 가능하다.


내부 클래스와 외부 클래스에 선언된 변수의 이름이 같을 땐 변수 앞에 'this' 또는 '외부 클래스명.this'를 붙여 서로 구별할 수 있다.


8-5 익명 클래스(anonymous class)

다른 내부 클래스들과는 달리 이름이 없다. 클래스의 선언과 객체의 생성을 동시에 하기 때문에 단 한번만 사용 될 수 있고 오직 하나의 객체만을 생성할 수 있는 일회용 클래스이다.

생성자를 가질 수 없으며, 하나의 클래스를 상속받는 동시에 인터페이스를 구현하거나 둘 이상의 인터페이스도 구현할 수 없다. 단 하나의 클래스를 상속받거나 인터페이스를 구현할 수 있다.


Posted by Hearthole
,

7. 인터페이스(interface)


7-1 인터페이스란?

인터페이스는 일종의 추상클레스이다. 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높아서 몸통을 갖춘 일반메서드 또는 멤버변수를 구성원으로 가질 수 없다. 오직 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외의  다른 어떠한 요소도 허용하지 않는다.


추상클래스 - 미완성 설계도

인터페이스 - 기본 설계도


7-2 인터페이스의 작성

인터페이스를 작성하는 것은 클래스를 작성하는 것과 같다. 다만 키워드로 class대신 interface를 사용한다는 것만 다르다. 클래스와 같이 접근제어자로 public 또는 default를 사용할 수 있다.


interface 인터페이스이름{

public static final 타입 상수이름 = 값;

public abstract 메서드이름(매개변수목록);

}


일반적인 클래스의 멤버들과 달리 인터페이스의 멤버들은 다음과 같은 제약사항이 있다.

- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.

- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.

[단, static메서드와 디폴트 메서드는 예외 (JDK1.8부터) ]

인터페이스에 정의된 모든 멤버에 예외없이 적용되는 사항이기 때문에 제어자를 생략할 수 있는 것이며, 편의상 생략하는 경우가 많다. 생략된 제어자는 컴파일러가 자동적으로 추가해준다.


원래는 모든 메서드는 추상메서드여야 했는데, JDK1.8부터 인터페이스에 static메서드와 디폴트 메서드(default method)의 추가를 허용하는 방향으로 변경되었다. 실무에서는 아직 JDK1.8을 사용하지 않는 곳이 많기에 JDK1.8이전과 이후의 규칙을 모두 알고 있어야 한다.


7-3 인터페이스의 상속

인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 달리 다중상속, 즉 여러개의 인터페이스로부터 상속을 받는 것이 가능하다.

클래스와 마찬가지로 자손인터페이스는 조상인터페이스에 정의된 멤버를 모두 상속받는다.

[인터페이스는 클래스와 달리 Object클래스와 같은 최고조상이 없다.]


7-4 인터페이스의 구현

인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며, 추상클래스가 상속을 통해 추상메서드를 완성하는 것처럼, 인터페이스도 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 한다. 클래스의 확장 키워드 'extends'처럼 인터페이스는 구현한다는 키워드 'implements'를 사용한다.

만일 구현하는 인터페이스의 메서드 중 일부만 구현한다면 abstract를 붙여 추상클래스로 선언해야 한다. 상속과 구현을 동시에 할 수 도 있다.

인터페이스의 메소드에는 'public abstract'가 생략되었을 뿐, 항상 붙어있으니 이를 오버라이딩 시 접근 제어자를 반드시 public으로 해줘야 한다.


7-5 인터페이스를 이용한 다중상속

자바는 다중상속을 허용하지 않는다는 것이 단점으로 부각되는 것의 대응으로 '자바도 인터페이스를 이용하면 다중상소깅 가능하다' 라는 것일 뿐, 인터페이스가 다중상속을 위해서 존재하는 것은 아니다. 오히려 자바에서 인터페이스로 다중상속을 구현하는 경우는 거의 없다. 

 만일 두 개의 클래스로부터 상속을 받아야 할 상황이라면, 두 조상클래스 중에서 비중이 높은 쪽을 선택하고 다른 한쪽은 클래스 내부에 멤버로 포함시키는 방식으로 처리하거나 어느 한쪽의 필요한 부분을 뽑아 인터페이스로 만든 다음 구현하도록 한다.

인터페이스를 새로 작성하지 않고 클래스를 내부에 포함시키는걸로 충분하지만, 인터페이스를 이용하면 다형적 특성을 이용할 수 있다는 장점이 있다.


7-6 인터페이스를 이용한 다형성

인터페이스 역시 클래스의 조상이라 할 수 있으므로 해당인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로의 형변환도 가능하다.

 

 인터페이스 Fightable을 클래스 Fighter가 구현했을 때, 다음과 같이 Fighter인스턴스를 Fightable타입의 참조변수로 참조하는 것이 가능하다.

Fightable f = (Fightable)new Fighter();

또는

Fightable f = new Fighter();


리턴타입이 인터페이스라는 것은 메서가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.


7-7 인터페이스의 장점


인터페이스를 사용하는 이유와 장점

-개발시간을 단축시킬 수 있다.

-표준화가 가능하다.

-서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.

-독립적인 프로그래밍이 가능하다.


7-8 인터페이스의 이해


-클래스를 사용하는 쪽(User)과 제공하는 쪽(Provider)이 있다.

-메서드를 사용(호출)하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면 된다.(내용은 몰라도 된다.)



7-9 디폴트 메서드와 static메서드


디폴트 메서드

디폴트 메서드는 앞에 default를 붙이며, 추상 메서드와 달리 일반 메서드처럼 몸통{}이 잇어야 한다. 디폴트 메서드 역시 접근 제어자가 public이며, 생략 가능하다.


새로 추가된 디폴트 메서드가 기존 메서드와 이름이 중복되어 충돌하는 경우

1. 여러 인터페이스의 디폴트 메서드 간의 충돌

- 인터페이스를 구현한 클래스에서 메서드를 오버라이딩해야 한다.

2. 디폴트 메서드와 조상클래스의 메서드 간의 충돌

- 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

 





Posted by Hearthole
,

6. 추상클래스(abstract class)


6-1 추상클래스란?

미완성 메서드(추상메서드)를 포함하고 있는 클래스이다. 인스턴스를 생성할 수 없으며, 상속을 통해서 자손클래스에 의해서만 완성될 수 있다.

키워드 'abstract'를 붙이기만 하면 된다. 이렇게 하면 클래스 선언부의 'abstract'를 보고 이클래스에는 추상메서드가 있으니 상속을 통해서 구현해주어야 한다는 것을 쉽게 알 수 있다.

또한 추상클래스는 추상메서드를 포함하고 있다는 것을 제외하고는 일반클래스와 전혀 다르지 않다. 추상클래스에도 생성자가 있으며, 멤버변수와 메서드도 가질 수 있다.


6-2 추상메서드(abstract method)

선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔 것이 추상메서드이다. 즉, 설계만 해놓고 실제 수행될 내용은 작성하지 않았기 때문에 미완성 메서드인 것이다.


/* 주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다 */

abstract 리턴타입 메서드이름();


추상클래스로부터 상속받는 자손클래스는 오버라이딩을 통해 조상인 추상클래스의 추상메서드를 모두 구현해주어야 한다. 만일 조상으로부터 상속받은 추성메서드 중 하나라도 구현하지 않는다면, 자손클래스 역시 추상클래스로 지정해 주어야 한다.



6-3 추상클래스의 작성

여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하기도 하고, 기존의 클래스의 공통적인 부분을 뽑아서 추상클래스로 만들어 상속하도록 하는 경우도 있다.


상속이 자손 클래스를 만드는데 조상 클래스를 사용하는 것이라면, 이와 반대로 추상화는 기존의 클래스의 공통부분을 뽑아내서 조상클래스를 만드는 것이라고 할 수 있다. 서로 반대되는 개념으로 이해하면 편하다.


추상화 - 클래스간의 공통점을 찾아내서 공통의 조상을 만드는 작업

구체화 - 상속을 통해 클래스를 구현, 확장하는 작업



Posted by Hearthole
,