모든 클래스들이 인스턴스화가 필요한 것이 아닙니다.
static 메서드와 static 필드들을 담은 클래스들을 인스턴스화를 시키지 않아도 기능들을 사용 할 수 있는데 굳이 인스턴스화를 시킬 필요는 없다고 봅니다.
역직렬화 기능을 담은 클래스가 있다고 가정해봅시다.
public class ObjectDeSerialization{
private static ByteArrayInputStream byteArrayInputStream;
private static ObjectInputStream objectInputStream;
public static byte[]makeByteDecodeArray(String encodeObject) {
return Base64.getDecoder().decode(encodeObject);
}
public static Object makeDecodeObject(byte[]bytes)throws 예외생략 {
byteArrayInputStream= new ByteArrayInputStream(bytes);
objectInputStream= new ObjectInputStream(byteArrayInputStream);
return objectInputStream.readObject();
}
}
이러한 클래스는 굳이 인스턴스를 만들지 않아도 됩니다. static 메서드와 static 필드들을 담고 있는데 인스턴스를 만들 필요는 없습니다.
그러면 인스턴스화를 막는 방법은 무엇이 있을까요??
👻 private 생성자
첫번째 방법으로는 private 생성자 를 사용하는 방법이 있습니다.
하지만 reflection 기능으로 인스턴스를 생성하는 방법이 있었죠??
@Test
@DisplayName("역직렬화 인스턴스 생성 테스트")
void ObjectDeSerializationTest()throws 예외 생략{
// given & when
// reflection 사용
Class<ObjectDeSerialization> objectDeSerializationClass = ObjectDeSerialization.class;
Constructor<ObjectDeSerialization> declaredConstructor = objectDeSerializationClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
ObjectDeSerialization objectDeSerialization = declaredConstructor.newInstance();
// then
assertThat(objectDeSerialization.getClass().getName()).isEqualTo(ObjectDeSerialization.class.getName());
}
그러면 예외를 던져 막아볼까요??
// 인스턴스 생성시에 AssertionError 예외 발생
private ObjectDeSerialization() {
throw new AssertionError();
}
인스턴스 생성시에 private 생성자에 AssertionError 예외를 던졌으니 예외가 발생 될 것입니다.
@Test
@DisplayName("역직렬화 인스턴스 생성 테스트")
void ObjectDeSerializationTest()throws 예외 생략{
// given & when
// reflection 사용
Class<ObjectDeSerialization> objectDeSerializationClass = ObjectDeSerialization.class;
Constructor<ObjectDeSerialization> declaredConstructor = objectDeSerializationClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
ObjectDeSerialization objectDeSerialization = declaredConstructor.newInstance();
// then
assertThat(objectDeSerialization.getClass().getName()).isEqualTo(ObjectDeSerialization.class.getName());
}
private 생성자를 사용한 경우 주석으로 왜 private 를 사용했는지 설명을 해야합니다.
// 인스턴스화를 막기위한 생성자입니다.
private ObjectDeSerialization() {
throw new AssertionError();
}
👻 abstract Class
두번째 방법으로는 abstract 를 사용하여 인스턴스를 생성하는 것을 막을 수 있습니다.
public abstract class ObjectDeSerialization{
private static ByteArrayInputStream byteArrayInputStream;
private static ObjectInputStream objectInputStream;
public static byte[]makeByteDecodeArray(String encodeObject) {
return Base64.getDecoder().decode(encodeObject);
}
public static Object makeDecodeObject(byte[]bytes)throws IOException, ClassNotFoundException{
byteArrayInputStream= new ByteArrayInputStream(bytes);
objectInputStream= new ObjectInputStream(byteArrayInputStream);
returnobjectInputStream.readObject();
}
}
인스턴스를 생성할려고하면 컴파일 에러가 나옵니다.
@Test
@DisplayName("역직렬화 인스턴스 생성 테스트")
void ObjectDeSerializationTest() {
// given & when & then
ObjectDeSerialization objectDeSerialization = new ObjectDeSerialization(); // 컴파일 에러!!!
}
또한 reflection 기능으로 생성을 하면 InstantiationException 예외가 발생합니다.
@Test
@DisplayName("역직렬화 인스턴스 생성 테스트")
void ObjectDeSerializationTest()throws 예외 생략 {
// given & when
// reflection 사용
Class<ObjectDeSerialization> objectDeSerializationClass = ObjectDeSerialization.class;
Constructor<ObjectDeSerialization> declaredConstructor = objectDeSerializationClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
// then
assertThrows(InstantiationException.class,()-> declaredConstructor.newInstance());
}
private 생성자를 사용해서 인스턴스 생성을 막아도 좋지만 abstract 를 사용하여 인스턴스를 막는 것만으로 충분할 것 같다는 생각이듭니다.
'Book > Effective Java' 카테고리의 다른 글
[Book] ITEM 9) try-finally 대신 try-with-resource 를 사용하라 (0) | 2022.03.19 |
---|---|
[Book] ITEM 8) finalizer 와 cleaner는 피하라 (0) | 2022.03.07 |
[Book] ITEM 7) 더이상 쓰지 않는 객체 레퍼런스는 없애자 (0) | 2022.03.04 |
[Book] ITEM 6) 불필요한 객체는 만들지 말자 (0) | 2022.03.03 |
[Book] ITEM 5) 리소스를 엮을 때는 의존성 주입을 선호하라 (0) | 2022.03.03 |
[Book] ITEM 3) private 생성자 또는 enum 타입을 사용해서 싱글톤으로 만들것 (0) | 2022.03.01 |
[Book] ITEM 2) 생성자의 매개변수가 많다면 빌더를 고려하라 (0) | 2022.02.26 |
[Book] ITEM 1) 생성자 대신 정적 (static) 팩토리 메서드를 고려해 볼 것 (0) | 2022.02.26 |