[Java] 제네릭 정리 및 활용

devdo·2022년 3월 18일
0

Java

목록 보기
41/56
post-thumbnail

제네릭(Generic) 이란?

제네릭(Generic) 은 클래스 / 인터페이스 / 메서드 등의 타입을 파라미터로 사용할 수 있게 해주는 역할을 한다.


제네릭 장점

  • 코드 재사용성: 다양한 타입에 대해 공통 코드를 사용 가능
  • 컴파일-타임 체크: 컴파일 시에 제네릭 코드 확인
  • 타입 안정성: 불필요한 데이터 추가를 제한
  • 컬렉션에서 사용: 컬렉션에 객체 타입 필요

예시

public class GenericsExample<T> {

    private T value;

    public GenericsExample(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public static <E> boolean contains(List<E> list, E item) {
        return list.contains(item);
    }

}

위의 코드와 같이 클래스 이름 옆에 <T>를 선언해 준 후
필드의 변수 타입을 모두 T로 선언해 주었다.

이후 타입 T는 객체를 생성할 때 해당 타입으로 변경된다.


💡 제네릭(Generic) <T>, <E> 차이

  • T : Type, 어떠한 유형이든 상관없음.
  • ? : 와일드 카드, 모든 타입 허용.
  • E : Element, List<E>: Collection을 말함

public class mainGe {

    public static void main(String[] args) {
        List<String> stringList = List.of("apple", "banana", "orange");
        System.out.println(contains(stringList, "banana")); // true

        GenericsExample<Integer> intExample = new GenericsExample<>(42);
        System.out.println(intExample.getValue()); // 42
    }

}

제네릭 타입 제한

extends를 사용하여 원하는 클래스의 객체만 허용하도록 사용할 수 있습니다.
ex. AnimalPrinter<T extends Animal>


활용예시

SpringBoot를 사용하면 JPA Repository에서 제네릭의 활용 예시를 잘 볼 수 있다.

1) SpringBoot JPARepository 내부 구조

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>
, QueryByExampleExecutor<T> {

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll()
	 */
	@Override
	List<T> findAll();

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
	 */
	@Override
	List<T> findAll(Sort sort);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable)
	 */
	@Override
	List<T> findAllById(Iterable<ID> ids);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
	 */
	@Override
	<S extends T> List<S> saveAll(Iterable<S> entities);

2) 직접사용

요청, 응답 객체로 활용

  • Req.class
@Data
public class Req<T> {

    private Header header;

    private T resBody;

    @Data
    public static class Header {
        private String responseCode;
    }

}
  • Result.class
@Getter
@AllArgsConstructor
public class Result<T> {

    private Integer code;

    private String message;

    private String detail;

    private T data;		// data 변수는 Result<T> T가 어떤 타입이든 유동적으로 그 T 타입으로 변하게 된다.

}

ResponseCode

@Getter
@AllArgsConstructor
public enum ResponseCode {

    SUCCESS_CODE(1000, "success"),
    
    ...
    
    private final Integer code;
    private final String message;
    

=> 응답값 구현

    @GetMapping("/list")
    @ApiOperation(value = "Paging List")
    public ResponseEntity<?> getAllWithPage(PageRequestDto pageRequestDto) {

        log.info("listPage, PageRequestDto: {}", pageRequestDto);

        Page<ContentDetailDto> contentWithPage = contentService.getAllWithPage(pageRequestDto);
        return ResponseEntity.ok(new Result<>(SUCCESS_CODE.getCode(), SUCCESS_CODE.getMessage(), null, contentWithPage));
    }
    

여기서 마지막 응답값으로 ResponseEntity 내 body 부분에 정리할 수 있는 것을 볼 수 있다.

return ResponseEntity.ok(new Result<>(SUCCESS_CODE.getCode(), SUCCESS_CODE.getMessage(), null, contentWithPage));


참고

profile
배운 것을 기록합니다.

0개의 댓글