영업 뛰다가 온, 남들과 조금 다른 주니어 개발자

영업하면서 배운 고객 중심적 사고, 비즈니스 통찰력 등을 총동원해서 서비스를 개발하고 있습니다. 영업 경험이 개발하는 과정에서 큰 역할을 하더라구요, 즐겁게 개발하고 있습니다!

Language/JAVA

[JAVA] generic class 코드로 이해하기!

브윗 2024. 8. 30. 14:38

너무 유용한 generic class!

처음 배웠는데 너무 유용해서 바로 가져옴 ㅎㅎ

 

 

Array 는 처음에 지정할 때 String 인지, int 인지 먼저 다 지정을 해줘야 하는데,

이런 stack 은 먼저 지정해주고, String , int, 상관 없이 어떤 데이터 타입을 나중에 넣던지 가능하다는 점!

 

완전 유용하다!!

좀 더 자세한 설명은 아래에!

 


Generic 이란?

  • 클래스나 메서드에서 사용할 데이터 타입을 미리 지정하지 않고, 나중에 실제로 사용할 때 그 타입을 지정할 수 있도록 하는 기능.

장점

  • 클래스나 method 내부에서 사용되는 객체의 타입 안정성을 높일 수 있음.
  • 반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있음
  • 타입에 대해 유연성과 안정성을 확보
  • 런타임 환경에 영향을 주지 않는 전처리 기술

 


 

참고로, 제네릭이 없을 시절에, 다양한 타입의 객체를 저장할 수 있는 클래스를 만들려면 Object 타입을 사용해야 했다고 함.

 

Object 타입을 사용하면 다양한 종류의 데이터를 하나의 변수나 컬렉션에 저장할 수 있다.

다만, 실제로 해당 데이터를 사용할 때는 원래 타입으로 캐스팅해야 할 때가 많다. 이 과정에서 타입 에러가 발생할 수 있다!

 

아래 예시처럼, Object 타입의 변수에서 원래 데이터를 사용하려면, 데이터를 원래 타입으로 캐스팅해야 한다.

Object obj = "Hello, World!";

// obj를 String으로 캐스팅
String str = (String) obj;

System.out.println(str.toUpperCase());  // HELLO, WORLD!

 

이 예시에서는 Object 타입의 obj 변수를 String으로 캐스팅하여 toUpperCase() 메서드를 호출했다.

캐스팅을 잘못하면 ClassCastException이 발생할 수 있다.

 

=> Object 타입의 단점

  • 타입 안전성 부족: Object 타입을 사용하면 실제로 데이터가 어떤 타입인지 알기 어렵고, 잘못된 캐스팅이 발생할 수 있다.
  • 가독성 문제: 코드에서 타입을 명확히 하지 않으면 다른 개발자나 자신이 나중에 읽을 때 혼란스러울 수 있다.

 

Generic class 에 대해서는 일단 서술형으로 된 것보다 코드로 확인하는 것이 훨씬 쉽다!

아래는 코드!

 

 

Generic class 는 클래스 이름 뒤에 꺽쇠<> 를 붙이고, 그 꺽쇠 속에 타입을 지정할 문자를 써준다!

일반적으로 T 를 사용한다고 함.

 

그래서 여기서 나의 Generic class 이름은 GStack<T>

package com.test.oop;

class GStack<T>{

    int tos;
    Object[] stck; //Object 는 클래스 중의 클래스. 최상위 클래스. 어떤 타입이 들어와도 됨.

    public GStack(){
        tos = 0;
        stck = new Object[10];

    }

    //10개의 데이터를 채울 수 있는 스텍에 데이터를 채운다 (입력)
    public void push(T item){
        if (tos == 10) return; //이 void 안에서의 return 은 이 조건문을 종료하는 것.
        stck[tos] = item;
        tos ++;
    }

    //10개의 데이터를 채울 수 있는 스텍에서 데이터를 빼낸다 (출력)
    public T pop(){
        if (tos == 0) return null; //이것도 조건문을 빠져나오는 것임. 참고로 여기선 null 을 써줘야하는 이유가 이 메소드는 무조건 리턴값을 받아야 하잖아. 그래서 뭐라도 적어줘야 함. 근데 우린 그냥 빠져나가고 싶으니까 null 을 적음.
        tos--;
        return (T)stck[tos];
    }
}


public class GenericTest {
    public static void main(String[] args){

       
        GStack<String> stringStack = new GStack<String>();  //GStack class 에 String type 의 값을 보내기 위해 컴파일러에게 언급해주는 과정.
        stringStack.push("Seoul");
        stringStack.push("Busan");
        stringStack.push("LA");

        for (int i = 0; i<3; i++){
            System.out.println(stringStack.pop());
        }

       // GStack<Integer> intStack = new GStack<Integer>(); <- 이렇게 Integer 를 넣을 수도 있음.

    }
}