<객체와 클래스>
<객체>
- 상태와 행동을 갖는다
프로그램에서 객체는 소프트웨어 객체로서 상태(변수)와 행동(메쏘드)를 갖는다 - 객체는 클래스로부터 생성된다
객체의 생성은 클래스의 인스턴스 생성과 같은 의미이다 - 객체의 초기화는 클래스의 생성자를 사용한다
- 객체가 속한 클래스가 그 객체의 자료형이다
- 객체 사용의 의미
- 객체의 변수를 읽거나 쓴다
- 객체의 메쏘드를 호출한다(객체에게 메시지를 보낸다)
- 객체와 클래스는 사실 의미가 다르지만 객체는 실세계 객체의 전자공학적 모델이어서 쉽게 구분이 가지 않는다 종종 객체를 클래스와 인스턴스 모두의 의미로 사용된다
자전거 – 객체, 자전거를 만드는 설계도 – 클래스
동일한 설계도로 많은 자전거를 만들 수 있다
<class>
- 객체를 생성하는 설계도이다
- 선언
class Name [extends Super] [implements Interface [,Interface, …]] {몸체}
클래스명에 알파벳, _, $을 사용한다. 관례적으로 대문자를 사용한다
상위 클래스명이 없을 경우 자동적으로 Object 클래스가 상위 클래스가 된다 - 하나의 파일 안에 여러 개의 클래스를 정의할 때
단지 한 개의 클래스에만 public 접근 변경자를 붙여야 한다 - 응용 프로그램 클래스와 애플릿 클래스
- 응용 프로그램 클래스는 main 메쏘드가 있으며 아래와 같이 고정된 형식으로 쓰인다
public static void main (String args[]) { ……. //몸체 } - 애플릿 클래스는 java.applet.Applet 클래스의 서브 클래스이므로 선언시 확장시켜야 한다
main 메쏘드가 없고, init 메쏘드가 있으며 그 형식은 고정되어 있고, 애플릿이 웹 브라우저로 읽혀 들어질 때 단 한 번 호출된다
public void init () { ……. //몸체 }
cf_1) start 메쏘드 : init가 호출된 후 start를 호출하며 또는 애플릿이 잠시 중단된 후 다시 실행이 계속되어야 할 때 start가 호출된다. 형식은 고정되어 있다
public void start () { ……. //몸체 }
cf_2) stop 메쏘드 : 애플릿의 실행이 멈추는 상황이 벌어질 때 호출된다. 그 형식은 고정되어 있다
public void stop () { ……. //몸체 }
cf_3) start, stop는 반드시 소스 코드내에 정의될 필요는 없다
- 응용 프로그램 클래스는 main 메쏘드가 있으며 아래와 같이 고정된 형식으로 쓰인다
- Modifier
- 클래스의 access modifier
package(access modifier를 따로 선언하지 않을 때)인 경우 그 클래스는 자신이 속한 패키지 안에서만 접근이 가능하고
public을 선언하면 그 클래스가 속해 있는 패키지 밖에서 그 클래스를 접근할 수 있다. 클래스를 위한 접근 속성 변경자는 public 뿐이다 - 클래스의 type modifier
- abstract
- abstract class 클래스명 { …….//클래스 몸체 }
- 공통으로 사용할 수 있는 상위 클래스를 선언할 때 많이 쓰인다
- 변수나 메쏘드의 선언문들이 들어 있지만, 실제로 인스턴스를 만들기 위한 코드가 없는 것이 일반 클래스와 다른 점이다
- 추상 클래스는 자신의 인스턴스를 만들지 못한다
- 추상 클래스는 추상 메쏘드를 가질 수 있
- final : final로 지정된 클래스는 하위 클래스를 갖지 못한다
- abstract
- 한정자의 적용 범위
- 클래스의 access modifier
한정자 |
클래스 |
멤버 변수 |
멤버 함수 |
지역 변수 |
abstarct |
v |
v |
v |
|
final |
v |
v |
v |
v |
native |
|
|
v |
|
static |
v |
v |
v |
|
syschronized |
|
|
v |
|
transient |
|
v |
|
|
volatile |
|
v |
|
|
private |
|
v |
v |
|
protected |
v |
v |
v |
|
public |
v |
v |
v |
|
- 상속과 멤버의 액세스 범위
한정자 |
클래스 |
클래스의 패키지 |
다른 패키지 |
|
디폴트 멤버 |
상속 |
v |
v |
|
접근 |
v |
v |
|
|
private 멤버 |
상속 |
v |
|
|
접근 |
v |
|
|
|
protected 멤버 |
상속 |
v |
v |
v |
접근 |
v |
v |
|
|
public 멤버 |
상속 |
v |
v |
v |
접근 |
v |
v |
v |
|
디폴트 클래스 |
접근 |
v |
v |
|
public 클래스 |
접근 |
v |
v |
v |
- 클래스 멤버와 인스턴스 멤버(멤버는 변수와 메쏘드를 뜻한다)
- 클래스 멤버의 참조
클래스 이름 . 멤버 이름 - 인스턴스 멤버 참조
인스턴스명 . 인스턴스 멤버명 - 클래스 멤버 변수의 초기화
일반적인 초기화와 정적 초기화 블록의 사용(static { 변수명 = 값; ….. }) - 인스턴스 멤버 변수의 초기화
일반적 초기화와 생성자의 사용
- 클래스 멤버의 참조
- 중첩 클래스
- 중첩 클래스란 다른 클래스의 멤버인 클래스를 의미한다
- 정적 중첩 클래스
- static으로 선언된다
- 정적 중첩 클래스는 클래스 멤버이다 즉, 정적 중첩 클래스를 포함하는 클래스의 인스턴스 멤버들을 참조할 수 없다
- 내부 클래스
- static으로 선언되지 않는 클래스이다
- 내부 클래스는 인스턴스 멤버이다 즉, 내부 클래스를 포함하는 클래스의 인스턴스 멤버들을 직접 참조할 수 있다
- 자신의 정적 멤버들을 정의할 수 없다
- 익명의 클래스는 이름이 없는 내부 클래스로서 코드의 가독성이 떨어지므로 잘 사용하지 않는다
- 중첩 클래스는 추상 클래스나 종단 클래스로 선언될 수 있으며 다른 멤버들과 마찬가지로public protected package private 접근 지정자를 붙일 수 있다
- Object 클래스
- 자바의 모든 클래스들 중에서 최상위 클래스이다
- 모든 종류의 객체가 가져야하는 기본적인 멤버 변수들과 메쏘드들을 제공한다
- 서브 클래스에서 치환될 수 있는 메쏘드
- clone()
- 다른 객체들로부터 같은 자료형의 객체들을 복제할 수 있다
- 기본적으로 객체들은 복제될 수 없으나 clone() 메쏘드는CloneNotSuportedException 예외 객체를 생성한다
- 그러므로 해당 클래스의 객체들을 복제하려면 그 클래스는 Cloneable 인터페이스를 구현해야 하며 clone() 메쏘드를 치환해야 한다
- clone() 메쏘드는 복제를 위하여 new 연산자를 사용하지 않으며 생성자를 호출하지도 않는다
- equals()
- 객체를 비교하는 것은 두가지 방법이 있다
첫째 : 두 객체가 동일한 객체인지 비교한다
둘째 : 두 객체의 내부값이 같은지 아닌지를 비교한다 - equals() 메쏘드는 둘째 방법를 수행한다
- 객체를 비교하는 것은 두가지 방법이 있다
- finalize() – 사용하지 않는 객체들을 정리한다
- toString() – 객체에 대한 String 객체 표현을 반환한다
- hashCode()
- clone()
- 서브 클래스에서 치환될 수 없는 메쏘드
- getClass()
- 자바 시스템은 Class라는 클래스를 갖고 있다 종단 메쏘드 getClass()는Class 클래스의 객체를 반환한다
- Class 클래스의 객체는 해당 클래스의 이름, 그것의 수퍼 클래스, 그것이 구현하는 인터페이스들 등에 대한 정보를 갖고 있다
- notify(), notifyAll()
다중 스레드들을 동기화시키는데 사용된다 - wait()
- getClass()
- 메쏘드
- access modifier type modifier returnType Name(parm) throws Exceptions
- return value
- 자바의 어떤 형이든 리턴할 수 있다.
void – 어떤 값도 리턴하지 않는다 - 리턴형이 클래스인 경우 반환되는 인스턴스는 리턴형 클래스의 인스턴스이거나 또는 그 서브 클래스이 인스턴스이어야 한다
- 리턴형이 인터페이스인 경우 그 인터페이스를 구현하는 클래스의 인스턴스이여야 한다
- 자바의 어떤 형이든 리턴할 수 있다.
- Method Modifier
- access modifier
- public
접근 : 모든 클래스에서 접근이 허용된다
상속 : 모든 클래스에 상속이 될 수 있다 - protected
접근 :
같은 패키지 내의 클래스는 접근이 허용된
또한 패키지가 달라도 그 클래스의 서브 클래스이면 허용된다
상속 :
그 클래스의 서브 클래스들에게 상속이 될 수 있다 - package (아무 것도 지정하지 않을 때)
접근 :
같은 패키지 내의 클래스는 접근이 허용된다
상속 :
그 클래스의 서브 클래스들에게 상속 될 수 있다 - private
접근 : 메쏘드를 선언한 클래스만 접근이 허용된다
상속 : 서브 클래스로 상속되지 않는다
- public
- type modifier
- static
static으로 선언된 메쏘드는 클래스 메쏘드이다
클래스 메쏘드에서는 클래스 변수만 사용할 수 있고 인스턴스 변수들을 사용할 수 없다 - final
메쏘드를 재정의 할 수 없다
변수에 사용하면 그 변수의 값은 상수가 된다 - abstract
추상 메쏘드는 리턴형과 이름, 인자 파라미터가 정의되지만, 메쏘드의 본체는 정의되지 않고 상속받는 하위 클래스에서 재정의해서 본체를 붙인다 - native
다른 언어로 작성된 메쏘드임을 나타낸다 - synchronized
쓰레드들을 동기화시킨다
- static
- access modifier
- Method Overloading
- 같은 이름의 메쏘드를 여러 개 정의할 수 있게 해준다
- 현재 클래스 안에 있는 메쏘드이든 상위 클래스에 있는 메쏘드이든 static으로 선언된 정적 메쏘드가 아니라면 overloading할 수 있다
- overloading되는 각 메쏘드들의 반환형은 같아야 한다
- Method Overriding(메쏘드 치환)
상위 클래스에 있는 메쏘드을 서브 클래스에서 같은 반환값, 같은 이름, 같은 개수의 파라미터를 갖는 메쏘드드를 정의할 때 치환된다
- Variale
- static variable
static 변경자를 사용하면 그 클래스의 모든 인스턴스들이 전부 이 변수에 접근 가능하게된다. 이것은 어떤 변수가 한 클래스의 여러 인스턴스 사이에 또는 그 클래스의 서브 클래스의 인스턴스들 사이에 변수가 공유되어야 하는 상황에 알맞는 도구가 될 수 있다 - instance variable
객체의 각각의 인스턴스에 존재한다. 즉 한 클래스에 대해 서로 다른 인스턴스들이 존재하며, 각기 같은 이름의 변수를 가질 수 있으나 자바에서는 각각의 변수에 서로 다른 값을 다른 위치의 메모리에 저장할 수 있다 - access modifier(메쏘드의 access modifier와 동일하다)
- type modifier
- static
클래스 변수임을 선언한다 - final
재정의가 불가능하다 즉 상수이다 - transient
이 변수는 직렬화(object serialization)되지 않아야 한다 - volatile
컴파일러가 변수에 대해 최적화를 수행하지 못하게 한다
- static
- 이미 정의된 인스턴스 변수
- null : 값이 아직 대입되지 않았다
- this : 한 변수의 현재 인스턴스를 명시적으로 가리킨다
- super : 상위 클래스를 가리킨다
- 변수의 치환
- 메쏘드에서 파라미터가 인스턴스 변수를 치환할 때
인스턴스 변수를 사용하려면 this를 사용한다 - 하위클래스에서 상위 클래스의 변수를 치환할 때
상위 클래스의 변수를 사용하려면 suer를 사용한다
- 메쏘드에서 파라미터가 인스턴스 변수를 치환할 때
- static variable
- 객체 사용하기
- 인스턴스 생성
- new 키워드는 어떤 형이든 객체를 생성할 수 있다. 예외가 있다면 기본 데이터 타입이다 –> 선언되면 메모리가 할당되므로
- String desc ;
desc = new String(10) ;
- 생성자 메쏘드
- 리턴형이 void이고, 생성자가 속한 클래스의 이름과 같은 메쏘드 이름을 가진다
- 다중 생성자는 메쏘드의 이름을 클래스의 이름과 일치시킨 여러 개의 메쏘드를 정의하는 것으로 만들 수 있다
- 생성자는 같은 클래스나 상위 클래스에 있는 다른 생성자를 호출할 수 있다. – this, super 키워드를 사용하여 현재 클래스나 상위 클래스의 생성자를 부르는 방식으로 생성자를 만드는 규칙을 확장한다
- 소멸자 메쏘드
- 이름이 finalize로 정해져 있다
- 리턴형이 void이며, java.object.Object 클래스에 정의되어 있는 finalize 메쏘드를 재정의하는 형태로 사용된다
- 수퍼 클래스로부터 상속된 메쏘드들에 의해 모르는 사이에 얻어진 자원들을 가지고 있을 수 있으므로 그 자원도 반납한다 즉, finalize 메쏘드 안에 super.finalize();를 마지막 라인에 넣어 준다
- Garbage Collection System
- 더이상 쓰지 않는 메모리를 찾아서 해제시켜 준다
- 객체가 더이상 참조가 되지 않는 순간 곧바로 쓰레기 수집이 일어나지는 않는다
이 작업은 필요할 때마다 시스템에서 알아서 수행이 된다 - 자바 프로그램이 끝나는 시점에서 finalize 메쏘드를 호출하는 것이 쓰레기 수집기가 발동하여 finalize 메쏘드가 자동적으로 호출되기를 기다리는 것보다 낫다
- destroy() 메쏘드
- 애플릿이 끝나고 없어질 때 호출되는 메쏘드이다
- init, start, stop 와 같이 애플릿 실행 상태와 관련된 메쏘드이다
- 이름이 destroy로 정해져 있다
- 리턴형이 void이며, public으로 선언되고, 파라메터가 없어야 한다
- 인스턴스 생성
- Inheritance
- 한 클래스를 확장하여 새로운 클래스를 만드는 것이다
- subclass, superclass
하위 클래스는 상위 클래스의 모든 멤버를 가지며, 추가로 정의된 특성을 가질수 있다
추가로 정의된 것들 중에 상위 클래스에서 정의된 것이 있으면 상위 클래스의 그 멤버는 상속 받지 않는다(overriding) - sinlgle inheritance : 한 클래스는 단지 한 개의 상위 클래스를 가진다
- static 또는 final로 정의된 메쏘드는 상속되지 않는다
- 상속을 정의하기 위해서 extends을 사용한다
public class Name extends Super { 클래스 몸체 } - 생성자들은 클래스이 멤버가 아니므로 서브 클래스로 상속되지 않는다
<Interface>
- 의미
- 인터페이스느 행위들에 대한 프로토콜을 정의한다
- 상수 값들과 구현부가 없는 메쏘드 정의들의 모임에 의해 표현된다
(메쏘드의 실행 코드를 포함하지 않는다) - 실제 메쏘드의 내용들은 나중에 설계하고 프로그램되어야 할 클래스들이 맡는다
- 장점
많은 클래스들이 같은 인터페이스를 동시에 사용하여 구현할 수 있다. 즉, 같은 인터페이스를 사용하는 클래스들은 인터페이스에서 제공하는 메쏘드들을 공통으로 쓸 수 있다 - 인터페이스 선언
인터페이스의 내용은 변수와 메쏘드들의 정의문으로 구성되어 있다
interface 인터페이스명 { 인터페이스 몸체 } - 인터페이스 변경자
- 클래스에서 사용하는 변경자를 모두 사용할 수 있다
- 대부분의 인터페이스들은 public으로 선언된다
그 이유는 변수와 메쏘드를 서로 다른 패키지 간에 공유하기 위해 쓰이기 때문이다
- 메쏘드
- 메쏘드를 위한 접근 변경자는 public과 package가 있다
- 인터페이스 안에서 메쏘드는 추상 메쏘드만 가능하다
변경자를 선언하지 않으면 명시적으로 abstract로 선언된다 그러므로, abstract를 사용하면 안된다 - 클래스에서와 마찬가지로 인터페이스에서도 메쏘드 overloading이 가능하다
- 변수
- 변수들을 위한 접근 변경자는 public과 package가 있다
- 인터페이스 안에서 선언된 변수는 단지 상수로만 가능하다
변경자를 사용하지 않으면 명시적으로 static final로 선언된다 그러므로, static final를 사용하면 안된다
- 상속
- 클래스처럼 다른 인터페이스를 상속할 수 있다
- extends를 사용한다
- 인터페이스들는 다중 상속이 가능하다
즉 한 인터페이스는 여러 개의 수퍼 인터페이스를 가질 수 있다
- 클래스에서 인터페이스를 사용하려면
인터페이스 정의후 클래스 선언시 implements 명령어를 사용한다
class name [entends superclass] implements interface1 [ , interface2 , …. ]- 클래스는 인터페이스로부터 상수를 상속 받는다
- 클래스는 구현되지 않은 메쏘드를 상속받아 구현한다
- 인터페이스 계층 구조는 클래스 계층 구조와 독립적이므로 클래스 계층 구조상의 위치와 무관하게 여러 클래스들이 동일한 인터페이스를 구현할 수 있다
- 클래스가 어떤 인터페이스를 구현한다는 것은 그 클래스가 인터페이스가 제공하는 프로토콜을, 즉 인터페이스가 선언한 모든 메쏘드들을 구현하겠다는 약속을 하는 것이다 하나의 메쏘드만 필요하다고 해서 나머지를 코딩하지 않으면 에러가 발생한다
-> 구현은 해야 하지만 필요없는 메쏘드가 너무 많은 경우 내부 클래스를 이용한 어댑터로 구현한다
<Package>
- 관련된 클래스들과 인터페이스들의 모음이다
패키지는 접근 보호와 이름 공간 관리 기능을 제공한다 - 클래스 선언
- 패키지를 선언하는 문장은 자바 프로그램 소스 코드의 가장 처음에 위치해야 한다
package 패키지명 ;
class A { ……. }
class B { ……. }
final class C { ……. }
abstract class D { ……. }
public class E { ……. } - 여러 개의 클래스를 하나의 파일로 저장할 때 한 개의 클래스만이public 접근 변경자를 사용한다 물론 main() 메쏘드도 public가 붙은 메쏘드내에 있어야 한다
- 패키지 이름은 자바의 이름 붙이기 규칙에 따르며 관례적으로 소문자를 쓴다
- 패키지 이름의 중복문제
도메인 이름을 역순으로 쓰는 방식을 이용하여 패키지 이름의 유일성을 보장하고 있다 - 어떤 소스 코드든지 한 소스 코드 안에서 패키지 선언문은 단지 한 개만 있어야 한다
- 패키지의 계층 구조 개념을 사용하기 위해서는 패키지 선언문 안에서 여러 개의 패키지 이름 사이에 점을 찍는 방식으로 정의하면 된다
- 패키지 이름을 선언하지 않은 경우
기본적으로 정해지는 ‘이름 없는’ 패키지에 포함된다
다른 패키지의 클래스들이 이 이름없는 패키지에 속한 클래스들을 참조할 수 없다
- 패키지를 선언하는 문장은 자바 프로그램 소스 코드의 가장 처음에 위치해야 한다
- 다름 패키지에 접근하기
- 다른 패키지 안에 있는 클래스나 메쏘드를 사용하려면 패키지의 완전한 이름을 클래스 이름 앞에 붙여서 사용하여야 한다
- import
- 한 클래스에서 다른 패키지를 참조하기 위해 사용된다
- 소스 코드 안에서 클래스 정의문들보다 앞에 위치 해야한다
import 패키지명 ; 예) import java.applet.* ; - import를 사용함으로써 코드의 길이가 짧아진다
- 기본적으로 java.lang.* 클래스는 자동적으로 참조한다
- CLASSPATH
클래스 파일들을 탐색하기 위한 디렉토리들 또는 zip 파일들의 목록이다
<Thread>
- Thread
- 자바에서 동시에 여러 개의 코드를 병렬적으로 수행할 수 있게 한다
- 프로세스와 달리 부모 프로세스 전체의 복사본을 만들지 않고, 필요한 코드만을 동시에 수행한다
- 여러 개의 thread가 동시에 데이터를 변경할 수 있으므로 thread의 동기화가 중요하다
cf_1)프로그램 : 컴파일을 통해 만들어낸 실행할 수 있는 파일
cf_2)프로세스 : 실제 메모리에 상주되어 실행되고 있는 코드
- 선언
- 자바에서 제공하는 thread 클래스를 확장한다
class 스레드 클래스명 extends Thread { ……. //몸체 } - Runnable 인터페이스를 구현한다
이 방법은 현재 있는 클래스가 어떻든 간에 클래스를 변경해야 할 필요가 없이 스레드로 변환될 수 있다
- 자바에서 제공하는 thread 클래스를 확장한다
- Thread 초기화, 제거, 이름이 있는 스레드
- 스레드도 클래스로 제공하므로 실제 실행되는 스레드는 당연히 스레드의 인스턴스이다
- 스레드의 인스턴스는 new 키워드를 사용하여 생성할 수 있다
- 객체의 현재의 인스턴스인 this가 스레드로 초기화된다
mainThread = new Thread(this) ;
어느 객체든지 Thread 클래스의 파라미터가 될 수 있다 - Thread 클래스를 상속받은 클래스일 수도 있다
mainThread = new MyThreadClass();
- 객체의 현재의 인스턴스인 this가 스레드로 초기화된다
- 스레드 제거
- 스레드 인스턴스를 명시적으로 선언하여 삭제할 필요가 없다(-> 자바의 쓰레기 수집기능) 대신 쓰레기 수집기에게 이 스레드 인스턴스로의 참조가 전부 없어졌다는 사시를 확실히 알 리는 것을 통해 삭제 작업을 돕는 일이 필요하다
- 스레드 인스턴스로의 참조값을 가지고 있는 변수에 null 값을 대입한다
Thread myThread = new Thread();
myThread.start();
myThread.stop();
myThread = null; - 이름이 있는 스레드
- 자바의 유효한 문자열이면 가능하며, 스레드의 이름을 붙이게 되면 스레드끼리 서로 구분할 수 있고, 부모 프로세스에서 이름을 가지고 원하는 스레드를 찾는데 편리하다
- 스레드를 생성할 때에 이름을 붙이려면 간단하게 문자열을 추가 인자 파라미터로 받아들이는 스레드 생성자를 사용하도록 한다
Thread myThread = new Thread(this,”My first named thread”);
My first named thread가 스레드의 이름이 된다 - Thread Method
- init
- 스레드가 맨 처음 시작될 때 호출된다
- 객체의 초기화나 그 외에 스레드가 시작될 때 처음 한 번만 실행되어야 할 어떤 작업을 코딩한다
- start
- 스레드의 실행을 시작하기 위해 호출된다
- 실제로 스레드를 생성하고 시작시키는 일을 한다
- stop
스레드의 실행을 중지시키는데 필요한 코드가 들어있다 - run
- C, C++의 main 함수와 거의 같은 역할을 한다
- 스레드에서 실제 실행되어야할 코드의 본체가 들어 있다
- getName
지정된 스레드 인스턴스에 할당된 이름을 리턴한다 - setName
- 스레드의 이름을 정하거나 변경할 수 있다
- 부모, 자신, 이 스레드로의 접근 권한을 가진 다른 메쏘드들이 스레드의 이름을 변경할 수 있다
- Thread 동기화
- 스레드들은 데이터 객체들을 따로 복사해서 가지고 있으므로, 여러 개의 스레드들이 같은 객체나 메쏘드에 접근하는 경우 주어진 시간에 접근하는지를 확신할 수 없으므로 예측하지 못한 결과를 얻을 수도 있다
그러므로 자바 동기화를 위한 논리체계를 사용하기 위해 synchronized 키워드를 사용한다 - synchronized
- 코드 불록을 수행하는 동안 객체를 잠그는(동기화) 데 쓰인다
어떤 스레드로 코드 블록을 수행하는 동안에 synchronized 키워드를 가지고 동기화된 객체를 변경할 수 없다 - synchronized 키워드는 메쏘드를 위한 변경자로도 쓰인다
이 경우 메쏘드를 실행하는 스레드가 한 시점에서 단지 한 개만이 존재하게 된다
- 코드 불록을 수행하는 동안 객체를 잠그는(동기화) 데 쓰인다
- 스레드들은 데이터 객체들을 따로 복사해서 가지고 있으므로, 여러 개의 스레드들이 같은 객체나 메쏘드에 접근하는 경우 주어진 시간에 접근하는지를 확신할 수 없으므로 예측하지 못한 결과를 얻을 수도 있다
<Exception>
- exception
- 자바는 복구 가능한 에러들을 예외라는 특별한 클래스로 다룬다
- 예외가 프로그램의 어느 부분에서도 명시적으로 처리되지 않는다면 이 예외는 자바 인터프리터로 전달되어 어떤 방법으로든 이 예외를 처리하거나 단순히 자신을 중단시킨다
- 자바의 모든 예외들은 java.lang.Exception 클래스에서 정의되고 있다
이미 존재하는 예외를 보강하려면
->메쏘드를 재정의
->변수를 다시 코딩
새로 예외를 만들려면
->java.lang.Exception 클래스를 확장한다 - 자바에서는 예외에 대한 처리를 꼭 요구하지는 않는다
- 예외를 위한 키워드들
- try
- 예외를 발생할 수 있는 코드 블록의 실행을 시도한다
- 어떤 문장이 예외를 발생시킬 때 블록 안의 남은 코드들은 전부 무시되고 try문 뒤의 첫 번째 catch or finally 문장으로 실행이 계속된다
- try문 뒷쪽에는반드시 catch or finally 문이 뒤따라야 한다
- catch
- 예외를 받는다. 예외가 발생되어 적절한 처리를 한다는 것을 표현한다
- 파라미터는 catch 불록 안에서만 쓰이는 예외 객체를 가지고 있는 변수이다
- finally
- 발생된 예외가 catch 문들 가운데 어느 것에도 해당되지 않을 때 취할 행동을 표현한다
- try or catch 문 다음에 존재한다
- throw
throw ( ExceptionObj ) ;- 자신의 예외를 생성시킬 때 사용된다
- throw 될 때 현재 코드의 수행이 중단되며, 이 예외는 호출한 루팅으로 전달되고 더 이상 다른 코드는 어딘가에서 그 예외가 잡히기 전까지는 수행되지 않는다
그리고 예외가 잡힌 곳에서 수행이 계속된다
- 예외 처리문의 표준구조
try {
//예외를 발생시키는 문
}
catch (ExceptionType1 e ) {
예외 type 1을 처리하는 문
}
catch (ExceptionType2 e ) {
예외 type 2을 처리하는 문
}
……………………………………
finally {
다른 모든 예외를 처리하는 문
}
- try
<Stream>
- stream
- 스트림은 자바에서 프로그램의 바깥(파일, 네트워, 디바이스, 다른 프로세스)과 데이터를 읽고 쓰는 수단이다
- 모든 자바의 스트림은 byte의 흐름으로 되어 있다
어떤 스트림은 다른 객체형을 쓸 수 있도록 허용하고 있지만, 내부적으로 이들 객체를 바이트로 변환하고 있다 - producer process
다른 프로세스들이 사용할 데이터를 만든다 - consumer process
다른 프로세스가 만들어낸 데이터를 사용한다 - output stream
생산자 프로세스에게서 나오는 정보들이다 - input stream
소비자 프로세스로 흐르는 정보들이다 - 스트림을 구성하는 정보들은 단지 일정 시간에 생산자 -> 소비자로 전달되는 데이터 블록의 흐름일 뿐이다.
단순한 byte에서부터 복잡한 object까지 블록이 될 수 있다 - 한 개의 프로세스가 여러개의 스트림을 동시에 가지면서 스트림에 따라 생산자나 소비자가 프로세스가 될 수 있다
- 각각의 스트림은 단지 한 개의 생산자와 한 개의 소비자만이 있을 수 있다
- 생산자와 소비자는 스트림 인터페이스를 통해 서로 직접 통신하지 않는다
->생산자와 소비자는 서로에 대해 알 필요가 없다
생산자는 단지 한 쪽 끝에서 데이터의 스트림을 생성하고 이것들은 자바의 스트림 처리 코드에게 넘어가며 여기서 데이터가 소비자에게 넘어간다 - 표준 자바 스트림들은 java.io 패키지에 있다
- 입력 스트림
- 입력 스트림에서 작동되는 메쏘드들
- read
- 입력 스트림에서 데이터를 읽어들인다
- 모든 read 메쏘드는 블로킹 읽기를 기반으로 한다
- 모든 read 메쏘드는 IOException 예외를 발생시킬 수 있다
- int read ( );
int read ( byte[] buffer );
int read ( byte[] buffer, int offset, int length );
리턴값은 읽혀진 바이트 수이다
더 이상 읽을 것이 없는 경우 -1을 리턴한다 - blocking read : read 메쏘드가 호출되었을 때 데이터가 전부 읽혀지거나 예외가 일어나기 전까지는 리턴되지 않는다
- skip
- 입력 스트림에서 나오는 바이트들 중 정해진 숫자만큼을 건너뛴다
- IOException 예외를 발생시킬 수 있다
- 데이터 스트림은 고정된 크기를 가지고 있지 않기 때문에 long형 파라미터에서 지정할 수 있는 개수보다 더많은 바이트 만큼 건너뛰어야 할 경우에는 skip 메쏘드를 두 번 써주어야 한다
- long skip ( long num );
리턴값은 건너뛴 바이트의 수를 나타내는 long형 값이다
호출될 때 입력 스트림의 끝에 있는 경우 -1을 리턴한다
- markSupported
markSupported();
인자가 없으며 mark가 주어진 입력 스트림에서 사용 가능한지를 알리는 boolean형 값을 리턴한다 - close
- 애플릿이나 응용프로그램에서 더 이상 사용되지 않는 입력 스트림을 닫을 때 사용한다
- 자바에서는 사용하지 않는 입력스트림을 자동적으로 닫는다. 그러나 더 이상 필요없는 프로그램의 리소스를 그때 그때 닫는 것이 좋다
- IOException 예외를 발생시킬 수 있다
- close();
- read
- 입력 스트림에서 작동이 보장되지 않는 메쏘드들
- available
- 블로킹을 시키지 않고도 데이터를 읽을 수 있는지를 그리고 read같은 다른 메쏘드가 호출되기 전에 처리할 수 있는 충분한 데이터가 있는지를 알아내는데 사용한다
그러나 available 메쏘드는 모든 입력 스트림에 대해서 올바른 정보를 리턴하지 않는다 - int available();
리턴값은 블로킹 되지 않고 읽을 수 있는 데이터를 바이트 수로 나타낸 정수형 값이다
- 블로킹을 시키지 않고도 데이터를 읽을 수 있는지를 그리고 read같은 다른 메쏘드가 호출되기 전에 처리할 수 있는 충분한 데이터가 있는지를 알아내는데 사용한다
- mark 와 reset
- 입력 스트림의 특정한 부분으로 돌아갈 필요가 있을 때 그 부분에 표시를 하기 위해 사용된다
- 모든 입력 스트림에서 사용 가능한 것은 아니다
markSupported 메쏘드가 특정한 입력 스트림에서 mark 메쏘드를 사용하는 것이 가능한지를 알려준다 - 입력 스트림에서 여러 개의 표시를 지정할 수 없다
- reset 메쏘드는 mark로 표시한 입력 스트림의 부분으로 돌아간다
- void mark ( int readLimit );
boolean markSupported ( );
void reset ( );
int형 인자는 reset 메쏘드를 호출하기 전에 입력 스트림에서 읽을 수 있는 데이터의 양을 가리킨다 - reset 메쏘드가 호출되기 전에 mark 메쏘드가 다시 호출되면 표시는 새로운 위치로 이동한다
- available
- 입력 스트림에서 작동되는 메쏘드들
- 출력 스트림
- 출력 스트림 메쏘드들
- write
- 스트림에 데이터를 쓴다
- 모든 write 메쏘드들은 블로킹 쓰기를 한다
- 모든 write 메쏘드들은 IOException 예외를 발생시킬 수 있다
- void write ( int b ) ;
void write ( byte[] buffer );
void write ( byte[] buffer, int offset, int length );
모두 리턴값이 없다
쓰는 동안 에러가 발생하는 것을 알아내는 한 가지 방법은 발생되는 예외를 잡는(catch) 것 뿐이다
- flush
- write 메쏘드가 상당 시간 블로킹 될 경우 버퍼에 저장된 출력 스트림의 모든 데이터를 강제적으로 출력 장치로 보내도록 한다
- write 메쏘드가 블로킹 되어 응용 프로그램에서 flush를 사용하여 강제적으로 데이터를 처리하려면 다른 thread를 통해 flush를 수행하여야 한다
- IOException 예외를 발생시킬 수 있다
- void flush ( );
- close
- 더 이상 사용하지 않는 출력 스트림을 닫는다
- 입력 스트림에서 사용하는 close 메쏘드와 개념적으로 같다
- IOException 예외를 발생시킬 수 있다
- void close ( );
- write
- 출력 스트림 메쏘드들