본문 바로가기

Java/information

[자바/JAVA] generic

저번 과제 복습

하나의 스트림으로 입력과 출력이 동시에 가능하지 않다.
프로그램을 기준으로 데이터가 들어오면 입력스트림이다.
프로그램을 기준으로 데이터가 나가면 출력스트림이다.
파일에 데이터를 저장하려면 출력 스트림을 사용해야 한다.

이미지 데이터는 InputStream 또는 Reader로 모두 읽을 수 있다. (x)
(Reader는 문자기반 스트림이기에 바이트로 된 이미지를 읽지 못한다)
Reader의 read()메소드는 1문자를 읽고 리턴한다.

InputStream의 read() 메소드는 1byte를 읽고 리턴한다.
InputStream의 read(byte[] b) 메소드는 읽은 바이트 수를 리턴한다.

InputStream의 read(byte[] b, int off, int len)메소드에 대한 설명
메소드의 리턴값은 읽은 바이트 수이다.
첫번째 매개값 b에는 읽은 데이터가 저장된다.
두번째 매개값 off는 첫 번째 매개값 b에서 데이터가 저장될 시작 인덱스이다.
세번째 매개값 len은 첫번째 매개값 b에서 데이터가 저장될 마지막 인덱스이다.(x)
(len개의 바이트를 읽고 매개값으로 주어진 배열에서 b[off]부터 len개까지 저장한다. 그리고 읽은 바이트 수를 리턴한다)

InputStreamReader는 InputStream을 Reader로 변환하는 보조 스트림이다.
BufferedInputStream은 데이터 읽기 성능을 향상시키는 보조스트림이다.
DataInputStream은 객체를 입출력하는 보조 스트림이다(x)
(DataInputStream은 자바의 기본형 데이터인 int, float, double, boolean등의 정보를 입력하는데 알맞은 보조스트림이다 )
PrintStream은 라인 단위로 출력할 수 있는 보조 스트림이다.


자바는 Serializable 인터페이스를 구현한 클래스만 직렬화할 수 있도록 제한하고 있다. Serializable 인터페이스는 필드나 메소드가 없는 빈 인터페이스이다. 객체를 직렬화할 때 private 필드를 포함한 모든 필드를 바이트로 변환해도 좋다는 표시 역할을 한다.
객체를 직렬화하면 바이트로 변환되는 것은 필드들이고 생성자나 메소드는 직렬화에 포함되지 않는다. 따라서 역직렬화 할 때에는 필드의 값만 복원된다. 하지만 모든 필드가 직렬화 대상이 되는 것은 아니고 필드 선언에 static 또는 transien가 붙어있는 경우에는 직렬화가 되지 않는다!

제네릭스와 컬렉션 프레임워크
배열은 기본 타입뿐만 아니라 클래스 타입의 배열도 만들수 있기 때문에 객체 저장소로 사용될 수 있다.
하지만 배열은 선언 시 정한 크기(저장 용량)를 변경할 수 없고, 항목을 저장, 삭제, 추가하는 메소드가 없기 때문에 직접 인덱스를 사용해야 한다.
이러한 불편함을 해결하기 위해 자바는 컬렉션 프레임워크를 제공한다.

자바는 널리 알려져 있는 자료구조를 사용해서 객체들을 효율적으로 추가, 삭제, 검색할 수 있도록 인터페이스와 구현 클래스를 java.util 패키지에서 제공한다.
이들을 총칭해서 컬렉션 프레임워크라고 부른다.
컬렉션은 객체의 저장을 뜻하고, 프레임워크란 사용방법을 정해놓은 라이브러리를 말한다. 
실제로 컬렉션 프레임워크는 사용방법을 정의한 인터페이스와 실제 객체를 저장하는 다양한 컬렉션 클래스(구현 클래스)를 제공한다.
컬렉션 프레임워크의 주요 인터페이스로는 List, Set, Map이 있다.

제네릭스
-제네릭(Generic)은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다.
즉, 클래스를 정의할 때는 info의 데이터 타입을 확정하지 않고 인스턴스를 생성할 때 데이터 타입을 지정하는 기능이 제네릭이다.
-매개변수화된 자료형(parameterized type)
-클래스에 적용 : 제네릭 클래스, 인터페이스에 적용 : 제네릭 인터페이스, 메소드에 적용 : 제네릭 메소드
-제네릭스를 이용하면 매개변수에 다양한 자료형의 데이터를 넘길 수 있음.
-제네릭은 코드 재사용성을 높여주며 중복의 제거와 타입 안정성을 동시에 추구

*Object타입을 사용하면 모든 종류의 자바 객체를 저장할 수 있다는 장점은 있지만 저장할 때 타입 변환이 발생하고 읽어올 때에도 강제 타입을 해야하기 때문에 전체 프로그램 성능에 좋지 않은 결과를 가져올 수 있으므로 제네릭이라는 해결책을 생각하게 되었다.
제네릭은 클래스를 설계할 때 구체적인 타입을 명시하지 않고, 타입 파라미터를 대체했다가 실제 클래스가 사용될 때 구체적인 타입을 지정함으로써 타입 변환을 최소화시킨다.
제네릭 타입을 이용하면 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거할 수 있다. 클래스나 인터페이스 이름 뒤에 <>를 붙이고 그 안에 타입 파라미터를 대문자 한글자를 준다.


제네릭 클래스
-클래스의 객체를 생성할 때에는 <> 기호를 사용하여 어떤 타입의 인수를 넣을지를 알려야함
제네릭 타입의 클래스나 인터페이스를 선언하는 방법: 이름 뒤에 <>부호를 붙이고 그 안에 타입 파라미터를 대문자 한글자로 준다. 
제네릭을 사용하는 가장 큰 장점 중의 하나는 타입변환(casting)을 다시 하지 않아도 되므로 불필요한 타입변환을 하지 않는 점으로 인해서 프로그램의 성능을 향상시킨다.
= public class MyClass<T>{...}, public interface MyInterface<T>{...}
-제네릭은 기본자료형을 사용할 수 없다 참조 자료형만 사용할 수 있기에 기본 자료형을 사용하고자 한다면, wrapper 클래스인 Integer, Double등을 이용

제네릭 타입은 두 개 이상의 멀티 타입 파라미터를 사용할 수 있는데, 이 경우 각 타입 파라미터를 콤마로 구분한다.
제네릭 타입 변수 선언과 객체 생성을 동시에 할 때 타입 파라미터 자리에 구체적인 타입을 지정하는 코드가 중복되어 복잡하므로 다이아몬드 연산자<>를 이용해서 간단하게 작성할 수 있다.

제네릭 메소드는 매개타입과 리턴 타입으로 타입 파라미터를 갖는 메소드이다.
=>public <T> Present<T> presenting(T t){...}
 리턴 타입 앞에 <>기호를 추가후 그 안에 타입 파라미터를 넣고, 리턴 타입과 매개 타입으로 타입 파라미터를 사용하면 된다.