<Java 사전학습_8>
- 내부 클래스(38강)
- 내부 클래스-람다식(39강)
- 내부 클래스-스트림(40강)
- 예외처리(41강)
- 자바 입출력(42~43강)
1. 내부 클래스(38강)
내부 클래스
| 종류 | 구현위치 | 사용할 수 있는 외부클래스 변수 | 생성 방법 | 
| 인스턴스 내부 클래스 | 외부 클래스 멤버 변수와 동일 | 외부 인스턴스 변수, 외부 전역 변수 | 외부 클래스를 먼저 만든 후 내부 클래스 생성 | 
| 정적 내부 클래스 | 외부 클래스 멤버 변수와 동일 | 외부 전역 변수 | 외부 클래스와 무관하게 생성 | 
| 지역 내부 클래스 | 메서드 내부에 구현 | 외부 인스턴스 변수, 외부 전역 변수 | 메서드를 호출할 때 생성 | 
| 익명 내부 클래스 | 메서드 내부에 구현, 변수에 대입하여 직접 구현 | 외부 인스턴스 변수. 외부 전역 변수 | 메서드를 호출할 때 생성되거나, 인터페이스 타입 변수에 대입할 때 new 예약어를 사용하여 생성 | 
package innerclass;
class OutClass{
	private int num = 10;
	private static int sNum = 20;
	private InClass inClass;
	
	public OutClass() {
		inClass = new InClass();
	}
	
	private class InClass{
		int inNum = 200;
//		static int sInNum = 100; //static사용불가
		
		void inTest() {
			System.out.println(num);
			System.out.println(sNum);
		}
	}
	
	public void usingInTest() {
		inClass.inTest();
	}
	
	static class InStaticClass {
		int iNum = 100;
		static int sInNum = 200;
		
		void inTest() {
//			num += 10; //외부 인스턴스 쓸 수 없음
			sNum += 10;
			System.out.println(sNum);
			System.out.println(iNum);
			System.out.println(sInNum);
		}
		
		static void sTest() {
			System.out.println(sNum);
			System.out.println(sInNum);
		}
	}
}
public class InnerTest {
	public static void main(String[] args) {
		OutClass outClass = new OutClass();
		outClass.usingInTest();
		
		OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
		sInClass.inTest();
	}
}
package innerclass;
class Outer {
	int outNum = 100;
	static int sNum = 200;
	
	Runnable runnable = new Runnable() {
		@Override
		public void run() {
			System.out.println("runnable");
		}
	};
	
	public Runnable getRunnable() {
		int localNum = 100;
		
		return new Runnable() {
			@Override
			public void run() {
				System.out.println(outNum);
				System.out.println(sNum);
				System.out.println(localNum);
			}			
		};
	}
}
public class LocalInnerTest {
	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.getRunnable().run();
		outer.runnable.run();
	}
}
2. 내부 클래스-람다식(39강)
람다식(lambda expression)
자바에서 함수형 프로그래밍을 구현하는 방식
클래스를 생성하지 않고 함수의 호출만으로 기능을 수행
 
함수형 프로그래밍(functional programming)
순수 함수(pure function)를 구현하고 호출함으로써 외부 자료에 부수적인 영향을 주지 않고 매개 변수만을 사용하도록 만든 함수
함수를 기반으로 구현
입력받은 자료를 기반을 수행되고 외부에 영향을 미치지 않으므로 병렬 처리 가능
안정적인 확장성 있는 프로그래밍 방식
 
람다식 구현하기
익명 함수 만들기
매개 변수와 매개 변수를 활용한 실행문으로 구현
(매개변수) -> {실행문;}두 수를 입력받아 더하는 add() 함수
int add(int x, int y) {
	return x + y;
}
(int x, int y) -> {return x + y;}함수 이름 반환 형을 없애고 →를 사용
{}까지 실행문을 의미
 
람다식 문법
매개변수가 하나인 경우 자료형과 괄호 생략
str -> {System.out.println(str);} 
매개변수가 두 개인 경우 괄호를 생략할 수 없음
x, y-> {System.out.println(x + y);} //잘못된 형식 
중괄호 안의 구현부가 한 문장인 경우 중괄호 생략
str -> System.out.println(str); 
중괄호 안의 구현부가 한 문장이라도 return문은 중괄호를 생략할 수 없음
str -> return str.length(); //잘못된 형식 
중괄호 안의 구현부가 반환문 하나라면 return과 중괄호 모두 생략
(x, y) -> x + y //두 값을 더하여 반환
str -> str.length() //문자열의 길이를 반환 
함수형 인터페이스
람다식을 선언하기 위한 인터페이스
익명 함수와 매개 변수만으로 구현되므로 단 하나의 메서드만을 가져야 함
두 개 이상의 메서드인 경우 어떤 메서드의 호출인지 모호해짐
@FunctionalInterface-함수형 인터페이스라는 의미, 여러 개의 메서드를 선언하면 에러 발생
 
익명 객체를 생성하는 람다식
자바는 객체 지향 언어로 객체를 생성해야 메서드가 호출됨
람다식 메서드를 구현하고 호출하면 내부에서 익명 클래스가 생성됨
람다식에서 외부 메서드의 지역변수는 상수로 처리됨(지역 내부 클래스와 동일한 원리)
package lambda;
@FunctionalInterface
public interface MyNumber {
	int getMaxNumber(int num1, int num2);
}
package lambda;
public class TestMyNumber {
	public static void main(String[] args) {
		MyNumber maxNum = (x, y) -> (x >= y)? x: y;
		
		int max = maxNum.getMaxNumber(10, 20);
		System.out.println(max); //20
	}
} 
객체지향과 람다식 비교
package lambda;
public interface StringConcat {
	public void makeString(String s1, String s2);
}
package lambda;
public class StringConcatImpl implements StringConcat{
	@Override
	public void makeString(String s1, String s2) {
		System.out.println(s1 + " " + s2);
	}
}
package lambda;
public class TestStringConcat {
	public static void main(String[] args) {
		StringConcatImpl sImpl = new StringConcatImpl(); //객체지향 방식
		sImpl.makeString("hello", "java");
		
		StringConcat concat = (s1, s2) -> System.out.println(s1 + " " + s2); //람다식 방식
		concat.makeString("hello", "java");
		
		StringConcat concat2 = new StringConcat() { //위의 람다식 실제 구현부
			@Override
			public void makeString(String s1, String s2) {
				System.out.println(s1 + " " + s2);
			}
		};
		concat2.makeString("hello", "java");
	}
} 
함수를 변수처럼 사용하는 람다식
| 프로그램에서 변수를 사용하는 경우 | 예시 | 
| 특정 자료형으로 변수 선언 후 값 대입하여 사용하기 | int a = 10; | 
| 매개변수로 전달하기 | int add(int x, int y); | 
| 메서드의 반환 값으로 반환하기 | return num; | 
 
인터페이스형 변수에 람다식 대입
interface PrintString {
	void showString(String str);
}
s -> System.out.println(s)
PrintString lambdaStr = s -> System.out println(s); //인터페이스형 변수에 람다식 대임
lambdaStr.showString("hello lambda_1");
package lambda;
interface PrintString {
	void showString(String str);
}
public class LambdaTest {
	public static void main(String[] args) {
		PrintString lambdaPrint = str -> System.out.println(str);
		lambdaPrint.showString("test");
		
		showMyString(lambdaPrint);
		
		PrintString reStr = returnPrint();
		reStr.showString("hello");
	}
	
	public static void showMyString(PrintString lambda) {
		lambda.showString("test2");
	}
	
	public static PrintString returnPrint() {
		return s -> System.out.println(s + " world");
	}
}
3. 내부 클래스-스트림(40강)
스트림(stream)
자료의 대상과 관계없이 동일한 연산을 수행
배열, 컬렉션을 대상으로 동일한 연산을 수행
일관성 있는 연산으로 자료의 처리를 쉽고 간단하게 함
 
한 번 생성하고 사용한 스트림은 재사용할 수 없음
자료에 대한 스트림을 생성하여 연산을 수행하면 스트림은 소모됨
다른 연산을 위해서는 새로운 스트림을 생성함
 
스트림 연산은 기존 자료를 변경하지 않음
자료에 대한 스트림을 생성하면 별도의 메모리 공간을 사용하므로 기존 자료를 변경하지 않음
 
스트림 연산은 중간 연산과 최종 연산으로 구분됨
스트림에 대해 중간 연산은 여러 개 적용될 수 있지만 최종 연산은 마지막에 한 번만 적용됨
최종 연산이 호출되어야 중간 연산의 결과가 모두 적용되는데 이를 ‘지연 연산’이라 함
package stream;
import java.util.Arrays;
import java.util.stream.IntStream;
public class IntArrayTest {
	public static void main(String[] args) {
		int[] arr = {1, 2, 3, 4, 5};
		
		IntStream stream = Arrays.stream(arr);
		int sum = stream.sum();
		System.out.println(sum); //15
		
		int count = (int)Arrays.stream(arr).count(); //스트림 재사용 불가
		System.out.println(count); //5
	}
}
package stream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class ArrayListTest {
	public static void main(String[] args) {
		List<String> sList = new ArrayList<String>();
		sList.add("Luppang");
		sList.add("Luka");
		sList.add("Louie");
		
		Stream<String> stream = sList.stream();
		stream.forEach(s -> System.out.println(s));
		
		for(String s : sList) { //위의 스트림, 람다식과 같은결과
			System.out.println(s);
		}
		
		sList.stream().sorted().forEach(s -> System.out.println(s));
	}
} 
reduce() 연산
정의된 연산이 아닌 프로그래머가 직접 지정하는 연산을 적용
최종 연산으로 스트림의 요소를 소모하며 연산 수행
배열의 모든 요소의 합을 구하는 reduce() 연산의 예
Array.stream(arr).reduce(0, *a, b) -> a + b));
//초기값 , (전달되는 요소, 각 요소가 수행해야 할 기능)두 번째 요소로 전달되는 람다식에 따라 다양한 기능을 수행
package stream;
import java.util.Arrays;
import java.util.function.BinaryOperator;
class CompareString implements BinaryOperator<String> {
	@Override
	public String apply(String s1, String s2) {
		if(s1.getBytes().length <= s2.getBytes().length)
			return s1;
		else return s2;
	}	
}
public class ReduceTest {
	public static void main(String[] args) {
		String[] greetings = {"안녕하세요~~~", "Hello", "Good morning", "반갑습니다."};
		
		System.out.println(Arrays.stream(greetings).reduce("", (s1, s2) -> {
				if(s1.getBytes().length >= s2.getBytes().length)
					return s1;
				else return s2;
			}
		)); //안녕하세요~~~
		
		String str = Arrays.stream(greetings).reduce(new CompareString()).get();
		System.out.println(str); //Hello
	}
}
4. 예외처리(41강)
오류
컴파일 오류(compile error)
프로그램 코드 작성 준 발생하는 문법적 오류
 
실행 오류(runtime error)
실행 중인 프로그램이 의도하지 않은 동작을 하거나(bug) 프로그램이 중지되는 오류
 
실행 오류 시 비정상 종료는 서비스 운영에 치명적
오류가 발생할 경우 로그(log)를 남겨 추후 이를 분석해 원인을 찾아야 함
자바는 예외처리를 통하여 프로그램의 비정상 종료를 막고 로그를 남길 수 있음
 
오류와 예외 클래스
시스템 오류(error)
가상 머신에서 발생, 프로그래머가 처리할 수 없음, 동적 메모리가 없는 경우, 스택 오버 플로우 등
 
예외(Exception)
프로그램에서 제어할 수 있는 오휴, 읽어 들이려는 파일이 존재하지 않는 경우, 네트워크 연결이 끊어진 경우
package exception;
public class ArrayExceptionTest {
	public static void main(String[] args) {
		int[] arr = {1, 2, 3, 4, 5};
		try {
			for(int i = 0; i <= 5; i++) {
				System.out.println(arr[i]);
			}
		}catch(ArrayIndexOutOfBoundsException e) {
				System.out.println(e);
				return;
		}finally { //try수행되면 finally는 무조건 수행됨
			System.out.println("finally");
		}
		System.out.println("end");
	}
}
package exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionTest {
	public static void main(String[] args) {		
		try (FileInputStream fis = new FileInputStream("a.txt")){
		} catch (IOException e) {
			System.out.println(e);
		}
		System.out.println("end");
	}
} 
try-with-resources문
리소스를 자동 해제하도록 제공해주는 구문
close()를 명시적으로 호출하지 않아도 try {} 블록에서 열린 리소스는 정상적인 경우, 예외가 발생한 경우 모두 자동 해제됨
해당 리소스가 AutoVloseable을 구현해야 함
FileInputStream의 경우 AutoCloseable을 구현하고 있음
 
예외 처리 미루기
Throws를 사용하여 예외 처리 미루기
메서드 선언부에 throws를 추가
예외가 발생한 메서드에서 예외처리를 하지 않고 이 메서드를 호출한 곳에서 예외 처리를 한다는 의미
main()에서 throws를 사용하면 가상 머신에서 처리됨
package exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ThrowsException {
	public Class loadClass(String fileName, String className) throws FileNotFoundException, ClassNotFoundException {
		FileInputStream fis = new FileInputStream(fileName);
		Class c = Class.forName(className);
		return c;
	}
	public static void main(String[] args) {
		ThrowsException ex = new ThrowsException();
		try {
			ex.loadClass("b.txt", "java.lang.String");
		} catch(FileNotFoundException e) {
			System.out.println(e);
		} catch (ClassNotFoundException e) {
			System.out.println(e);
		} catch (Exception e) {
			System.out.println(e);
		}
		System.out.println("end");
	}
} 
다중 예외 처리 시 주의사항
예외가 다양한 경우 가장 최상위 클래스인 Exception클래스에서 예외를 처리할 수 있음
단 Exception클래스는 모든 예외 클래스의 최상위 클래스이므로 가장 마지막 블록에 위치해야 함
 
사용자 정의 예외
JDK에서 제공되는 예외 클래스 외에 사용자가 필요에 의해 예외 클래스를 정의하여 사용
기존 JDK 예외 클래스 중 가장 유사한 클래스에 상속
기본적으로 Exception에서 상속해도 됨
package exception;
public class IDFormatException extends Exception{
	public IDFormatException(String message) {
		super(message);
	}
}
package exception;
public class IDFormatTest {
	private String userID;
	public String getUserID() {
		return userID;
	}
	public void setUserID(String userID) throws IDFormatException {
		if(userID == null) {
			throw new IDFormatException("아이디는 null이 될 수 없습니다.");
		}
		else if(userID.length() < 8 || userID.length() > 20) {
			throw new IDFormatException("아이디는 8자 이상, 20자 이하로 쓰세요.");
		}
		
		this.userID = userID;
	}
	public static void main(String[] args) {
		IDFormatTest idTest = new IDFormatTest();
		String userID = null;
		
		try {
			idTest.setUserID(userID);
		} catch (IDFormatException e) {
			System.out.println(e); //exception.IDFormatException: 아이디는 null이 될 수 없습니다.
		}
		
		userID = "1234567";
		
		try {
			idTest.setUserID(userID);
		} catch (IDFormatException e) {
			System.out.println(e); //exception.IDFormatException: 아이디는 8자 이상, 20자 이하로 쓰세요.
		}
	}
}
5. 자바 입출력(42~43강)
스트림
네트워크에서 자료의 흐름이 물과 같다는 의미에서 유래
다양한 입출력 장치에 독립적으로 일관성 있는 입출력을 제공하는 방식
입출력이 구현되는 곳-파일 디스크, 키보드, 마우스, 메모리 네트워크 등
 
스트림의 구분
대상 기준
입력 스트림 / 출력 스트림
 
자료의 종류
바이트 스트림 / 문자 스트림
 
기능
기반 스트림 / 보조 스트림
 
입력 스트림과 출력 스트림
입력 스트림
대상으로부터 자료를 읽어 들이는 스트림
 
출력 스트림
대상으로 자료를 출력하는 스트림
 
바이트 단위 스트림과 문자 단위 스트림
바이트 단위 스트림
동영상, 음악 파일 등을 읽고 쓸 때 사용
 
문자 단위 스트림
바이트 단위로 자료를 처리하면 문자는 깨짐
2바이트 단위로 처리하도록 구현된 스트림
 
기반 스트림과 보조 스트림
시반 스트림
대상에 직접 자료를 읽고 쓰는 기능의 스트림
 
보조 스트림
직접 읽고 쓰는 기능은 없이 추가적인 기능을 더해주는 스트림
보조 스트림은 직접 읽고 쓰는 기능은 없으므로 항상 기반 스트림이나 또 다른 보조 스트림을 생성자 매개변수로 포함함
package stream.inputstream;
import java.io.IOException;
public class SystemInTest {
	public static void main(String[] args) {
		System.out.println("알파벳 하나를 쓰고 엔터를 누르세요.");
		int i = 0;
		try {
			while((i = System.in.read()) != '\\n') {
				System.out.print((char)i);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
} 
Scanner 클래스
java.util 패키지에 있는 입력 클래스
문자뿐 아니라 정수, 실수 등 다른 자료형도 읽을 수 있음
여러 대상에서 자료를 읽을 수 있음(콘솔, 파일 등)
package stream.inputstream;
import java.util.Scanner;
public class ScannerTest {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		
		String name = scanner.nextLine();
		int num = scanner.nextInt();
		
		System.out.println(name);
		System.out.println(num);
	}
} 
Console 클래스
System.in을 사용하지 않고 콘솔에서 표준 입력을 할 수 있음
이클립스와는 연동되지 않음
command창에서 입력
 
바이트 단위 스트림-InputStream
바이트 단위 입력용 최상위 스트림
추상 메서드를 포함한 추상 클래스로 하위 클래스가 구현하여 사용
package stream.inputstream;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamTest {
	public static void main(String[] args) {
		FileInputStream fis = null;
		int i = 0;
		
		try {
			fis = new FileInputStream("input.txt");
			while((i = fis.read()) != -1) {
				System.out.print((char)i);
			}
		} catch (IOException e) {
			System.out.println(e);
		} finally {
			try {
				fis.close();
			} catch (IOException e) {
				System.out.println(e);
			}
		}
	}
} 
FileInputStream 클래스
파일로부터 자료를 읽어 들이는 스트림
읽어 들일 파일이 경로에 없는 경우 예외 발생
package stream.inputstream;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamTest2 {
	public static void main(String[] args) {
		try(FileInputStream fis = new FileInputStream("input2.txt")) {
			byte[] bs = new byte[10];
			int i;
			while((i = fis.read(bs)) != -1) {
				for(int j = 0; j < i; j++) {
					System.out.print((char)bs[j]);
				}
				System.out.println();
			}
		} catch(IOException e) {
			System.out.println(e);
		}
	}
} 
바이트 단위 스트림-OutputStream
바이트 단위 출력용 최상위 스트림
추상 메서드를 포함한 추상 클래스로 하위 클래스가 구현하여 사용
package stream.outputstream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest {
	public static void main(String[] args) {
		byte[] bs = new byte[26];
		byte data = 65;
		for(int i = 0; i < bs.length; i++) {
			bs[i] = data++;
		}
		
		try(FileOutputStream fos = new FileOutputStream("output.txt")) {
			fos.write(bs, 2, 10);
		} catch (IOException e) {
			System.out.println(e);
		}
		System.out.println("end");
	}
} 
flush()와 close() 메서드
출력 버퍼를 비울 때 flush() 메서드 사용
close() 메서드 내부에서 flush()가 호출되므로 close() 메서드가 호출되면 출력 버퍼가 비워짐
 
문자 단위 스트림-Reader
문자 단위로 읽는 최상위 스트림
하위 클래스에서 상속받아 구현함
 
문자 단위 스트림-Writer
문자 단위로 쓰는 최상위 스트림
하위 클래스에서 상속받아 구현함
package stream.writer;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterTest {
	public static void main(String[] args) {
		try(FileWriter fw = new FileWriter("writer.txt")) {
			fw.write("A");
			char[] cbuf = {'B', 'C', 'D'};
			fw.write(cbuf);
			fw.write("안녕하세요");
			fw.write(cbuf, 1, 2);
			fw.write("123");
		} catch(IOException e) {
			System.out.println(e);
		}
	}
} 
보조 스트림
실제 읽고 쓰는 스트림이 아닌 보조적인 기능을 추가하는 스트림
데코레이터 패턴
FilterInputStream과 FilterOutputStream이 보조 스트림의 상위 클래스
생성자의 매개변수로 또 다른 스트림을 가짐
 
InputStreamReader와 OutputStreamWriter
바이트 단위로 읽거나 쓰는 자료를 문자로 변환해주는 보조 스트림
package stream.decorator;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputStreamReaderTest {
	public static void main(String[] args) {
		try(InputStreamReader irs = new InputStreamReader(new FileInputStream("reader.txt"))) {
			int i = 0;
			while( (i = irs.read()) != -1) {
				System.out.print((char)i);
			}
		}catch(IOException e) {
			System.out.println(e);
		}
	}
} 
Buffered 스트림
내부적으로 8192바이트 배열을 가지고 읽거나 쓰기 기능을 제공하여 속도가 빨라짐
package stream.decorator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopyTest {
	public static void main(String[] args) {
		long milliseconds = 0;
		int len = 0;
		
		try(FileInputStream fis = new FileInputStream("a.exe");
				FileOutputStream fos = new FileOutputStream("b.exe");
				BufferedInputStream bis = new BufferedInputStream(fis);
				BufferedOutputStream bos = new BufferedOutputStream(fos)) {
			
			milliseconds = System.currentTimeMillis();
			int i;
			while((i = fis.read()) != -1) {
				bos.write(i);
				len++;
			}
			milliseconds = System.currentTimeMillis() - milliseconds;
		}catch(IOException e) {
			System.out.println(e);
		}
		System.out.println(len);
		System.out.println(milliseconds);
	}
} 
DataInputStream과 DataOutputSream
자료가 메모리에 저장된 0, 1 상태 그대로 읽거나 쓰는 스트림
package stream.decorator;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataInOutStreamTest {
	public static void main(String[] args) {
		try(FileOutputStream fos = new FileOutputStream("data.txt");
				DataOutputStream dos = new DataOutputStream(fos)) {
			dos.write(100);
			dos.writeInt(10);
			dos.writeChar('a');
			dos.writeUTF("hello");
		}catch(IOException e) {
			System.out.println(e);
		}
		
		try(FileInputStream fis = new FileInputStream("data.txt");
				DataInputStream dis = new DataInputStream(fis)) {
			System.out.println(dis.read());
			System.out.println(dis.readInt());
			System.out.println(dis.readChar());
			System.out.println(dis.readUTF());
		}catch(IOException e) {
			System.out.println(e);
		}
	}
} 
직렬화(serialization)
인스턴스의 상태를 그대로 저장하거나(serialization) 다시 복원(deserialization)하는 방식
파일에 쓰거나 네트워크로 전송
직렬화는 인스턴스 내용이 외부로 유출되는 것이므로 프로그래머가 직렬화 의도를 표시해야 함
package stream.serialization;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Person implements Serializable{ //직렬화하겠다는 의도를 표시
	String name;
	transient String title;
	
	public Person() {}
	public Person(String name, String title) {
		this.name = name;
		this.title = title;
	}
	
	public String toString() {
		return name + ", " + title;
	}
}
public class SerializationTest {
	public static void main(String[] args) throws ClassNotFoundException {
		Person p1 = new Person("Kim", "Manager");
		try(FileOutputStream fos = new FileOutputStream("serial.dat");
				ObjectOutputStream oos = new ObjectOutputStream(fos)) {
			
			oos.writeObject(p1);
		} catch(IOException e) {
			System.out.println(e);
		}
		
		try(FileInputStream fis = new FileInputStream("serial.dat");
				ObjectInputStream ois = new ObjectInputStream(fis)) {
			
			Object obj = ois.readObject();
			if(obj instanceof Person) {
				Person p = (Person)obj;
				System.out.println(p);
			}
		}catch(IOException e) {
			System.out.println(e);
		}
	}
} 
그 외의 입출력 클래스
File 클래스
파일 개념을 추상화한 클래스
입출력 기능은 없고 파일의 속성 경로, 이름 등을 알 수 있음
 
RandomAccessFile 클래스
입출력 클래스 중 유일하게 파일 입출력을 동시에 할 수 있는 클래스
파일 포인터가 있어서 읽고 쓰는 위치의 이동이 가능
다양한 자료형에 대한 메서드가 제공됨
package stream.others;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
	public static void main(String[] args) throws IOException {
		RandomAccessFile rf = new RandomAccessFile("random.txt", "rw");
		rf.writeInt(100); //4바이트, 4
		System.out.println(rf.getFilePointer());
		
		rf.writeDouble(3.14); //8바이트, 12
		System.out.println(rf.getFilePointer());
		
		rf.writeUTF("안녕하세요"); //3바이트*5+2바이트, 29
		System.out.println(rf.getFilePointer());
		
		rf.seek(0); //위치초기화
		
		int i = rf.readInt();
		double d = rf.readDouble();
		String str = rf.readUTF();
		
		System.out.println(i);
		System.out.println(d);
		System.out.println(str);
	}
}'공부기록 > 사전학습' 카테고리의 다른 글
| Java 사전학습_7 (0) | 2022.11.19 | 
|---|---|
| Java 사전학습_6 (0) | 2022.11.19 | 
| Java 사전학습_5 (0) | 2022.11.19 | 
| Java 사전학습_4 (1) | 2022.11.02 | 
| Java 사전학습_3 (1) | 2022.10.31 | 
댓글