남잭슨의 개발 블로그

[Java/Android]Java Generic 제너릭 타입 - 개념,사용법,활용법 본문

Android

[Java/Android]Java Generic 제너릭 타입 - 개념,사용법,활용법

남잭슨 2017. 10. 28. 19:30

Genric

Java Genric 타입이란 무엇인가?


Genric은 일반적인 이란 뜻을 가진 단어이다.


프로그래밍의 Generic은

- 일반적인 코드를 작성하고, 이코드를 다양한 타입의 객체에 대하여 재사용하는 프로그래밍 기법

- 클래스에서 사용할 타입을 클래스 외부에서 설정하는 타입

- Java 1.5부터 추가되었으며 주로 java Collection에서 많이 사용된다.



Geric이 이해가 안된다면 , 우리가 많이 쓰는 ArrayList를 생각을 해보자.


List<string> strList = new ArrayList<>();
List<object> objList = new ArrayList<>();


위처럼 ArrayList의 기능은 똑같지만 , 리스트에 담는 내용물은 다르다.

위처럼 List의 기능은 같지만, 사용하는 타입이 다를때, Generic 타입을 사용한다.

ArrayList는 ArrayList<T>로 선언되어 있으며,

해당 객체를 생성할때 T의 타입이 정해진다.


아래에는 예시 코드를 참조하자 .


class Test<T>{
	private T t;
	 
    public void set(T t) {
        this.t = t;
    }
 
    public T get() {
        return t;
    }
}


T 는 Genric 변수이다. 타입이 아직 정해져 있지않다 .

아래는 Test<T> 클래스를 사용한 예시이다.


	public static void main(String[] args) {
		
		Test<String> test = new Test();
		test.set("test");
		System.out.println(test.get());
	}

실행 결과 : test


Test<T>의 T대신 String을 사용하였기 때문에

메소드 set(T)대신 set(String) 으로 사용되었고,

메소드 get()은 return T; 대신 return String;이 된것이다.


Test내에서 사용할 T의 변수를 선언하면서 생성하였다.




아래는 Generic의 문법 및 기타 사용법이다.


아래는 Inertface Generic 사용법이다.

Generic이 두개 필요할때 <T1,T2> 이렇게 사용하면 된다.

interface InterfaceSample<T1, T2> { T1 testMethod1(T2 t); T2 testMethod2(T1 t); }

아래는 구현체이다

class TestSampleInerfaceImp implements InterfaceSample<String, Integer> { @Override public String testMethod1(Integer t) { return null; } @Override public Integer testMethod2(String t) { return null; } }


아래는 Method Generic Type 사용법이다.

메소드 제너릭 타입은 Class에 Generic Type을 선언하지 않고, 각 메소드마다 Generic Type을 선언해 사용할수 있다.

아래의 코드 처럼

메소드의 파라미터의 T 이 선언되어 있다면, 리턴타입 바로앞에 <T> 제너릭 타입을 선언해주어야한다.

메소드의 파라미터에 <T>가 선언되어 있다면, ReturnType 앞에 <T>를 선언하자.

class TestMethod {
    public static <T> List<T> method(List<T> list, T item) {
    	list.add(item);
        return list;
    }
}






아래는 WildCard Generic Type 사용법이다.

Generic 타입에는 <?>도 존재한다.

?는 알수없는 타입이며, 사용법으로는 아래와같다

<?> : 모든 객체 자료형, 내부적으로는 Object로 인식

<? super 객체형> : 명시된 객체자료형의 상위 객체, 내부적으로는 Object로 인식

<? extends 객체자료형> : 명시된 객체자료형을 상속한 하위객체, 내부적으로는 명시된 객체 자료형으로 인식

class TestWildCard {
	 
    public List<? extends Object> wildMethod1() {
           return new ArrayList<Long>();
    }

    public <T> List<? extends String> wildMethod12 (T t) {
           return new ArrayList<String>();
    }

    public List<?> method3() {
           return new ArrayList<>();
    }
}


 Generic Type 사용시 주의해야할 문법들이다.


- Generic Type으로는 전역변수(Static)를 선언할수 없다.

- Generic Type으로는 인스턴스를 생성할수 없다.


타입의 매개변수는 T 말고도 존재한다


E - Element

K - Key

N - Number

T - Type

V - Value


Generic 타입이 인스턴스화 될때, 컴파일러는 타입파라미터와 관련된 정보를 제거한다.

제너릭을 사용하기 이전의 라이브러리 등과 호완성을 유지하기 위함.







아래에는 Android 개발중 Generic을 사용한 예시이다.


Android 개발중 Error리스트를 보여주는 ErrorDialog를 만들게 되었다.


RecylerView로 구성된 에러리스트들을 띄워주는 다이얼로그를 구현하였다 .


에러리스트를 모듈화하는 작업을 하다보니 , 대부분의 객체 리스트들에서 이 에러리스트 다이어로그를 사용하게되었고,

여러타입의 객체들의 에러리스트를 띄워주는 Dialog를 만들게되었다.


아래 코드는 RecyclerView의 어댑터이다

<T extends CommonBean>의 제너릭 타입을 사용하고 있다.

CommonBean의 자식 객체만 해당 타입이 될수 있다.

CommonBean의 error와 msg 변수를 사용할수 있다.

public class ErrorAdapter<T extends CommonBean> extends RecyclerView.Adapter<ErrorAdapter.ViewHolder>{
    Context context;
    int resourceId;
    private View view;
    List<T> list ;

    public class ViewHolder extends RecyclerView.ViewHolder{
        public TextView col1, col2;

        public ViewHolder(View view) {
            super(view);
            col1 = (TextView)view.findViewById(R.id.col_1);
            col2 = (TextView)view.findViewById(R.id.col_2);
        }
    }

    public ErrorAdapter(Context context, int textViewResourceId, List<T> list){
        this.context = context;
        this.list = list;
        resourceId = textViewResourceId;
    }
    public ErrorAdapter(Context context, int textViewResourceId, T obj){
        list = new ArrayList<T>();
        list.add(obj);
        this.context = context;
        resourceId = textViewResourceId;
    }
    @Override
    public ErrorAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        view = LayoutInflater.from(parent.getContext()).inflate(resourceId, parent, false);
        return new ErrorAdapter.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ErrorAdapter.ViewHolder holder, final int position) {
        holder.col1.setText(list.get(position).getError());
        holder.col2.setText(list.get(position).getMsg());
    }

    @Override
    public int getItemCount() {
        return list.size();
    }
}


아래는 에러를 띄워주는 다이어로그이다.

기본 AlertDialog를 상속받았고,

onListener Interface를 사용하여 콜백함수를 받아서 사용하였다

마찬가지로 생성자에 <? extends CommonBean>을 사용하여 구현하였다

public class ErrorDialog extends AlertDialog{
    private AlertDialog dialog = this;
    private Context context;

    private ErrorDialog.OnListener mListener;
    public interface OnListener {
        void ok();
    }
    public ErrorDialog(Context context, List<? extends CommonBean> list , final OnListener listener ) {
        super(context);
        this.context = context;
        mListener=listener;

        //에러메시지 가공
        //List obj = Arrays.asList(errorMsg.split("\n"));

        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        View convertView = (View) inflater.inflate(R.layout.dialog_errorlist, null);
        Button btnok = (Button) convertView.findViewById(R.id.btn_ok);


        //리싸이클러뷰
        RecyclerView rv = (RecyclerView) convertView.findViewById(R.id.rv_list);
        RecyclerView.LayoutManager lm = new LinearLayoutManager(context);
        rv.setLayoutManager(lm);
        ErrorAdapter adapter=new ErrorAdapter(context,R.layout.renderer_error_list,list);
        rv.setAdapter(adapter);


        setView(convertView);
        setIcon(R.drawable.ic_info);
        setTitle("Error Message");

        btnok.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
                listener.ok();
            }
        });

    }

}

 


아래는 다이어로그를 구현한 코드이다.

 new ErrorDialog(context,errorList , new ErrorDialog.OnListener() {
                                @Override
                                public void ok() {}
                            }).show();

Error Dialog의 생성자 파라미터 errorList자리에는 CommoBean을 상속받은 객체로 구성된 List를 넣어주면된다.

List<? extends CommonBean>






참조 http://lng1982.tistory.com/240



Comments