안드로이드 추상 클래스 이용한 퍼미션 권한 설정. 2-2

에서 만든 java 소스를 코틀린으로 변환 수정



BaseActivity.kt 

//////////////////////////////////////////////////////////////////////////////////////////

abstract class BaseActivity : AppCompatActivity() {


    abstract val setLayout: Int


    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)


        setContentView(setLayout)

    }



    private val PERMISSION_REQUEST: Int = 1000



    /**인터페이스 등록.*/

    interface PermissionCheckListener {

        fun permissionCheckFinish()

    }


    /**클래스 내 사용할 퍼미션 체크 리스너 (setter 구현 방법이 특이함.)

     * 온 크레딧 바로 아래 생성 되어야 한다

     * */

    lateinit var permissionCheckListener: PermissionCheckListener


    /**

     * 스트링 배열로 퍼미션 체크.

     */

    fun permissionCheck(strings: Array<String>): Boolean {

        // 변수 사용시 리턴 타입 지정.

        // var check = false


        // 변수 사용안하고 바로 리턴시켜 버림.


        //안드로이드 마시멜로 이후 퍼미션 체크.

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            for (i in 0 until strings.size) {

                if (ContextCompat.checkSelfPermission(this, strings[i]) == PackageManager.PERMISSION_DENIED) {

                    ActivityCompat.requestPermissions(this, strings, PERMISSION_REQUEST)

                    // check = true

                    // break

                    return true

                }

            }

        }

        //return check

        return false

    }



    /**

     * 거부를 했을때 처리

     * 다시보지 않기 체크 후 거부를 하면 설정에서 권한을 허용하도록 요청.

     * 허용하지 않을 경우 앱 사용 을 못함..

     * 처리를 잘못하면 무한 반복할 경우가 생김.

     */

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {


        super.onRequestPermissionsResult(requestCode, permissions, grantResults)


        if (requestCode == PERMISSION_REQUEST) {

            //안드로이드 마시멜로 이후 퍼미션 체크.

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                for (i in grantResults.indices) {

                    if (grantResults[i] == 0) {

                        if (grantResults.size == i + 1) {

                            permissionCheckListener?.permissionCheckFinish()

                        }

                    } else {


                        // 거부한 이력이 있으면 true를 반환한다.

                        if (shouldShowRequestPermissionRationale(permissions[i])) {

                            ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST)

                            

                        } else {


                           AlertDialog.Builder(this)

                                .setTitle("다시보지않기 클릭.")

                                .setMessage(permissions[i] + " 권한이 거부되었습니다 설정에서 직접 권한을 허용 해주세요.")

                                .setNeutralButton("설정") { dialog, which ->


                                    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)

                                    intent.data = Uri.parse("package:$packageName")

                                    startActivity(intent)

                                    Toast.makeText(applicationContext, "권한 설정 후 다시 실행 해주세요.", Toast.LENGTH_SHORT).show()

                                    finish()

                                }

                                .setPositiveButton("확인") { dialog, which ->

                                    Toast.makeText(applicationContext, "권한 설정을 하셔야 앱을 사용할 수 있습니다.", Toast.LENGTH_SHORT)

                                        .show()

                                    finish()

                                }

                                .setCancelable(false)

                                .create().show()

                        }// shouldShowRequestPermissionRationale /else

                    } // 권한 거절

                } // for end

            }//Build.VERSION.SDK_INT  end

        }//requestCode  end

    }


}

//////////////////////////////////////////////////////////////////////////////////////////




MainActivity에서 사용 방법.


Manifest에 

<uses-permission android:name="android.permission.CAMERA" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

퍼미션 등록 확인.


MainActivity.kt

//////////////////////////////////////////////////////////////////////////////////////////

class MainActivity : BaseActivity() {


    override val setLayout = R.layout.activity_main


    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)


        permissionCheckListener = object : PermissionCheckListener {

            override fun permissionCheckFinish() {

                Log.e("log", "start Activity")

            }

        }


        if (permissionCheck(arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE))) {

            return

        }

        permissionCheckListener?.permissionCheckFinish()

    }

}



//////////////////////////////////////////////////////////////////////////////////////////


코틀린 클래스 정의



클래스는 class 키워드를 사용하여 선언하며, 자신의 맴버 속성(변수)과 맴버 함수를 가질 수 있다.

예 ) class Friend(/**생성자 */){

// 클래스 내부.

}


클래스 접근 제한자.


final

: 클래스에 지정하면 서브 클래스(상속)를 만들 수 없다.

코틀린에선 클래스와 클래스 맴버 모두 기본적으로 final 이다.


open 

: final과 반대의 의미를 가진다. open을 지정한 클래스는 서브 클래스(상속가능)를 만들 수 있고

클래스 맴버에 open을 지정하면 슈퍼 클래스의 맴버를 서브클래스에서 오버라이딩 할 수 있다.

abstract

: 클래스에 지정하면 추상 클래스가 되며 인스턴스를 생성할 수 없다.(자바와 동일)

추상 클래스는 대개 구현 코드가 없는 추상 함수를 맴버로 갖지만, 구현 코그가 있는 맴버 함수도 같이

가질 수 있다. abstract 맴버 함수는 기본적으로 open이다.


클래스 상속

open을 사용하여 클래스를 상속할 수 있다.

클래스의 맴버변수, 맴버함수에 open을 사용하여 상속할 수 있다.

이때 서브 클래스에서는 overrride 하여 사용한다.





인터페이스 정의.


interface 키워드 사용한다. 구현코드가 없는 추상 함수를 갖지만, 구현코드가 있는 확장함수도 포함할 수 있다.




추상클래스 정의.


abstract 키워드 사용한다. 추상클래스를 상속받은 서브 클래스에서는 추상클래스의 추상 함수들을 반드시 오버라이딩 해야한다.


통합내용.

인터페이스와 추상 클래스는 상호 운용이 가능하고 둘다 접근제한은 open 이다.

추상 클래스는 하나만 상속이 가능하며 인터패이스는 여러개 구현이 가능하다.


object.


객체선언

: 클래스 대신 객체를 선언하고 생성

하나의 인스턴스만 생성하고 공유하는 싱글톤 구현

클래스 처럼 객체 선언에도 속성과 함수  및 초기화 블럭 사용. 단 생성자는 가질 수 없다.


동반객체

: 클래스 내부에 객체 선언을 하면 포함하는 클래스의 인스턴스를 생성하지 않아도 객체의 선언의 함수와 속성

을 사용할 수 있다. (static)

최상위 수준 함수를 사용해도 동일한 효과를 볼 수 있다.

자바에서의 static 처럼 companion object 하면 된다.(private 한 팩토리 함수)


객체표현식

:익명 객체를 생성하는 방법(익명 내부 클래스.)

리스너에 사용시 

test.setOnClickListener(object : View.OnClickListener {

        override fun onClick(v: View?) {

                       

            }

        })

        이런식으로 사용.


중첩 클래스와 내부 클래스.

클래스 내부에 선언된 클래스

:중첩 클래스 - 중첩클래스는 외부 클래스의 맴버를 참조할 수 없다.

:내부 클래스 - 내부 클래스는 외부클래스의 맴버를 참조할 수 있다.

inner 키워드 사용.

대이터 클래스.

: data 키워드를 지정하면 데이터 클래스가 된다.

기본 생성자에 속성을 지정해야 한다.



































'Kotlin > study' 카테고리의 다른 글

Retrofit, RxJava, AndroidProject  (0) 2019.01.30
isNullOrBlank or isNullOrEmpty  (0) 2018.11.19
코틀린 apply,let 함수  (0) 2018.08.24


안드로이드 액티비티 & 프래그먼트.



액티비티 : 하나의 뷰(xml)에 하나의 액티비티만 사용.




프래그먼트 : 하나의 액티비티에 다수의 프래그먼트 사용.{


.add() tag : 나중에 프래그먼트를 검색하기 위한 선택적 태그 이름. (findFragmentByTag( tag ))


.replace() : 기존의 프래그먼트를 제거하고 새로운 프래그먼트로 대체.


.addToBackStack() name : 트랜잭션이 커밋 된 후에 기억되고 나중에 스택에서 꺼내 졌을때 트랜잭션을 되돌릴 것을 의미.  


findFragmentByTag는 add / replace 메서드 또는 addToBackStack 메서드로 추가 된 태그를 검색합니다.

}



프래그먼트




    /**

     * add : 프래그먼트를 추가 합니다. 프래그먼트는 선택적으로 뷰를 가질 수 있습니다.

     *id: Int, : 레이아웃 지정. (xml)

     * fragment: Fragment, : 화면에 보여질 프래그먼트.

     * tag: String? = null, : 프래그먼트 태그 지정.(findFragmentByTag (tag) 로 검색)

     * backStackCheck: Boolean = false : 트랜잭션 커밋 후 스택에 저장된 후 상위 프래그먼트가 제거되면 스택에 저장된

     * 프래그먼트를 불러온다.

     *

     * findFragmentByTag는 add / replace 메서드 또는 addToBackStack 메서드로 추가 된 태그를 검색합니다.

     */

    protected fun addFragment(id: Int, fragment: Fragment, tag: String? = null, backStackCheck: Boolean = false) {



        if (backStackCheck) {

            supportFragmentManager

                    .beginTransaction()

                    .add(id, fragment, tag)

                    .addToBackStack(tag)

                    .commit()

        } else {

            supportFragmentManager

                    .beginTransaction()

                    .add(id, fragment, tag)

                    .commit()

        }

    }



    /**

     * replace : 기존의 프래그먼트를 제거하고 새로운 프래그먼트로 대체 합니다. 프래그먼트는 선택적으로 뷰를 가질 수 있습니다.

     *id: Int, : 레이아웃 지정. (xml)

     * fragment: Fragment, : 화면에 보여질 프래그먼트.

     * tag: String? = null, : 프래그먼트 태그 지정.(findFragmentByTag (tag) 로 검색)

     * backStackCheck: Boolean = false : 트랜잭션 커밋 후 스택에 저장된 후 상위 프래그먼트가 제거되면 스택에 저장된

     * 프래그먼트를 불러온다.

     *

     * findFragmentByTag는 add / replace 메서드 또는 addToBackStack 메서드로 추가 된 태그를 검색합니다.

     */

    protected fun replaceFragment(id: Int, fragment: Fragment, tag: String? = null, backStackCheck: Boolean = false) {


        if (backStackCheck) {

            supportFragmentManager

                    .beginTransaction()

                    .replace(id, fragment, tag)

                    .addToBackStack(tag)

                    .commit()

        } else {

            supportFragmentManager

                    .beginTransaction()

                    .replace(id, fragment, tag)

                    .commit()

        }

    }


'Android > study' 카테고리의 다른 글

MVP 패턴  (0) 2019.04.25
안드로이드 코틀린 프로젝트 디펜던시  (0) 2019.01.25
레트로핏, okhttp  (0) 2018.08.27
RxJava  (0) 2018.07.30

안드로이드 액티비티 


상속을 이용한 베이스() 만들기.




안드로이드 스튜디오 프로젝트 생성.



퍼미션 관련 권한 자동화 시킬려니 동작이 안됨.



/////

/////java

/////

/**

 * 추상화 클래스  상속전용.

 */

abstract class BaseActivity extends AppCompatActivity {


    abstract protected int setContentViewLayout();



    @Override

    protected void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(setContentViewLayout());

        Log.e("bear", "BaseActivity start");

        //무언가 하나를 불러내면 딱 하고 끝나서

        // 여러 가지 신경안써도 되는 것....어떻게 해야하지????

        // onRequestPermissionsResult 이것을 baseActivity에서 처리하고 싶다는 건데.

    }



    /**

     * 프래그먼트 add

     * backStackCheck 기본적으로 true

     * .addToBackStack(tag)

     */

    protected void addFragment(int id, Fragment fragment) {

        addFragment(id, fragment, null, true);

    }


    protected void addFragment(int id, Fragment fragment, boolean backStackCheck) {

        addFragment(id, fragment, null, backStackCheck);

    }


    protected void addFragment(int id, Fragment fragment, String tag) {

        addFragment(id, fragment, tag, true);

    }



    protected void addFragment(int id, Fragment fragment, String tag, boolean backStackCheck) {


        //프래그먼트 등록 후 back 누르면 이전 activity 또는 fragment로 이동한다.

        if (backStackCheck) {

            getSupportFragmentManager()

                    .beginTransaction()

                    .add(id, fragment, tag)

                    // 백스텍에 이름이 없거나 널이면 프래그먼트클래스 이름을 등록

                    // 아니면 백스텍 이름을 등록 삼항연산자 앞에가 true : false

                    .addToBackStack(tag)

                    .commit();

        } else {


            getSupportFragmentManager()

                    .beginTransaction()

                    .add(id, fragment, tag)

                    .commit();

        }

    }



    protected void replaceFragment(int id, Fragment fragment) {

        replaceFragment(id, fragment, null, true);

    }


      protected void replaceFragment(int id, Fragment fragment, boolean backStackCheck) {

        replaceFragment(id, fragment, null, backStackCheck);

    }

    protected void replaceFragment(int id, Fragment fragment, String tag) {

        replaceFragment(id, fragment, tag, true);

    }


    //

    protected void replaceFragment(int id, Fragment fragment, String tag, boolean backStackCheck) {


        if (backStackCheck) {

            getSupportFragmentManager()

                    .beginTransaction()

                    .replace(id, fragment, tag)

                    // 백스텍에 이름이 없거나 널이면 프래그먼트클래스 이름을 등록

                    // 아니면 백스텍 이름을 등록 삼항연산자 앞에가 true : false

                    .addToBackStack(tag)

                    .commit();

        } else {

            getSupportFragmentManager()

                    .beginTransaction()

                    .replace(id, fragment, tag)

                    .commit();

        }

    }



    @Override

    public void onBackPressed() {


        Log.w("bear", "fragment Size : " + getSupportFragmentManager().getBackStackEntryCount());

        if (getSupportFragmentManager().getBackStackEntryCount() == 0) {

            Log.w("bear", "000");

            super.onBackPressed();

        } else {

            Log.w("bear", "1111");

            super.onBackPressed();

        }

    }


    /**

     * 액티비티 전환

     */

    protected void changeActivity(Context context, Class<?> activity, boolean activityFinish) {


        Intent intent = new Intent(context, activity);


        startActivity(intent);

        if (activityFinish) {

            finish();

        }

    }



    /**

     * 퍼미션 검사 리스너.

     */

    protected interface PermissionCheckListener {

        /***/

        void permissionCheckFinish();

    }


    /**

     * 리스너 등록.

     */

    protected PermissionCheckListener permissionCheckListener;


    /**

     * 온 크레딧 바로 아래 생성 되어야 한다

     */

    public void setPermissionCheckListener(PermissionCheckListener permissionCheckListener) {

        this.permissionCheckListener = permissionCheckListener;

    }


    private final int PERMISSION_REQUEST = 1000;



    /**

     * 이게 BaseActivity 에 들어갈 필요가 있는가?????

     * 스트링 배열로 퍼미션 체크.

     * 필요할때만 if 문으로 처리.

     * true 일 경우 퍼미션 팝업.

     */

    public boolean permissionCheck(String[] strings) {

        boolean check = false;

        // //안드로이드 마시멜로 이후 퍼미션 체크.

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            for (int i = 0; i < strings.length; i++) {

                if (ContextCompat.checkSelfPermission(this, strings[i]) == PackageManager.PERMISSION_DENIED) {

                    ActivityCompat.requestPermissions(this, strings, PERMISSION_REQUEST);

                    check = true;

                    break;

                }

            }

        }

        return check;

    }


    /**

     * 거부를 했을때 처리

     * 다시보지 않기 체크 후 거부를 하면 설정에서 권한을 허용하도록 요청.

     * 허용하지 않을 경우 앱 사용 을 못함..

     * 처리를 잘못하면 무한 반복할 경우가 생김.

     */

    @Override

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {


        super.onRequestPermissionsResult(requestCode, permissions, grantResults);


        if (requestCode == PERMISSION_REQUEST) {

            // //안드로이드 마시멜로 이후 퍼미션 체크.

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                for (int i = 0; i < grantResults.length; i++) {


                    if (grantResults[i] == 0) {

                        if (grantResults.length == (i + 1)) {


                            // 인터페이스 콜백으로 리턴됨.

                            permissionCheckListener.permissionCheckFinish();

                        }

                    } else {


                        // 거부한 이력이 있으면 true를 반환한다.

                        if (shouldShowRequestPermissionRationale(permissions[i])) {

                            ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST);

                            break;


                        } else {

                            new AlertDialog.Builder(this)

                                    .setTitle("다시보지않기 클릭.")

                                    .setMessage(permissions[i] + " 권한이 거부되었습니다 설정에서 직접 권한을 허용 해주세요.")

                                    .setNeutralButton("설정", new DialogInterface.OnClickListener() {


                                        @Override

                                        public void onClick(DialogInterface dialog, int which) {

                                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);

                                            intent.setData(Uri.parse("package:" + getPackageName()));

                                            startActivity(intent);

                                            Toast.makeText(getApplicationContext(), "권한 설정 후 다시 실행 해주세요.", Toast.LENGTH_SHORT).show();

                                            finish();

                                        }

                                    })

                                    .setPositiveButton("확인", new DialogInterface.OnClickListener() {


                                        @Override

                                        public void onClick(DialogInterface dialog, int which) {

                                            Toast.makeText(getApplicationContext(), "권한 설정을 하셔야 앱을 사용할 수 있습니다.", Toast.LENGTH_SHORT).show();

                                            finish();

                                        }

                                    })

                                    .setCancelable(false)

                                    .create().show();


                        }// shouldShowRequestPermissionRationale /else

                    } // 권한 거절

                } // for end

            }//Build.VERSION.SDK_INT  end

        }//requestCode  end

    }



}



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


public class MainActivity extends BaseActivity {


    @Override

    protected int setContentViewLayout() {

        return R.layout.activity_main;

    }


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        setPermissionCheckListener(new PermissionCheckListener() {

            @Override

            public void permissionCheckFinish() {


                Log.w("bear", "MainActivity 여기서 시작해야 한다.");

                addFragment(R.id.layoutContainer, BlankFragment.newInstance());

                addFragment(R.id.layoutContainer, BlankFragment.newInstance("bear"));

                replaceFragment(R.id.layoutContainer, BlankFragment.newInstance("bear", "bear22  "));


            }

        });



        if (permissionCheck(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE})) {

            Log.e("bear", "퍼미션 체크를 시도.");

            return;

        }


        permissionCheckListener.permissionCheckFinish();

    }



}


public class MainActivity extends BaseActivity {


    @Override

    protected int setContentViewLayout() {

        return R.layout.activity_main;

    }


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        setPermissionCheckListener(new PermissionCheckListener() {

            @Override

            public void permissionCheckFinish() {


                Log.w("bear", "MainActivity 여기서 시작해야 한다.");

                addFragment(R.id.layoutContainer, BlankFragment.newInstance());

                addFragment(R.id.layoutContainer, BlankFragment.newInstance("bear"));

                replaceFragment(R.id.layoutContainer, BlankFragment.newInstance("bear", "bear22  "));


            }

        });



        if (permissionCheck(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE})) {

            Log.e("bear", "퍼미션 체크를 시도.");

            return;

        }


        permissionCheckListener.permissionCheckFinish();

    }



}


public class MainActivity extends BaseActivity {


    @Override

    protected int setContentViewLayout() {

        return R.layout.activity_main;

    }


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        setPermissionCheckListener(new PermissionCheckListener() {

            @Override

            public void permissionCheckFinish() {


                Log.w("bear", "MainActivity 여기서 시작해야 한다.");

                addFragment(R.id.layoutContainer, BlankFragment.newInstance());

                addFragment(R.id.layoutContainer, BlankFragment.newInstance("bear"));

                replaceFragment(R.id.layoutContainer, BlankFragment.newInstance("bear", "bear22  "));


            }

        });



        if (permissionCheck(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE})) {

            Log.e("bear", "퍼미션 체크를 시도.");

            return;

        }


        permissionCheckListener.permissionCheckFinish();

    }



}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

abstract class BaseFragment extends Fragment {


    abstract protected int setContentViewLayout();


    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container,

                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment

        Log.e("bear", "BaseFragment start");

        return inflater.inflate(setContentViewLayout(), container, false);

    }

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/**

 * 기본 프래그먼트 작업.

 */

public class BlankFragment extends BaseFragment {


    @Override

    protected int setContentViewLayout() {

        // onCreateView 오버라이딩 할 필요없다.

        return R.layout.fragment_blank;

    }



    private static final String ARG_PARAM1 = "param1";

    private static final String ARG_PARAM2 = "param2";


    private String mParam1;

    private String mParam2;



    public BlankFragment() {

        // Required empty public constructor

    }


    public static BlankFragment newInstance() {

        return new BlankFragment();

    }


    public static BlankFragment newInstance(String param1) {

        BlankFragment fragment = new BlankFragment();

        Bundle args = new Bundle();

        args.putString(ARG_PARAM1, param1);

        fragment.setArguments(args);

        return fragment;

    }



    public static BlankFragment newInstance(String param1, String param2) {

        BlankFragment fragment = new BlankFragment();

        Bundle args = new Bundle();

        args.putString(ARG_PARAM1, param1);

        args.putString(ARG_PARAM2, param2);

        fragment.setArguments(args);

        return fragment;

    }


    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        if (getArguments() != null) {

            if (getArguments().getString(ARG_PARAM1) != null) {

                mParam1 = getArguments().getString(ARG_PARAM1);

            }


            if (getArguments().getString(ARG_PARAM2) != null) {

                mParam2 = getArguments().getString(ARG_PARAM2);

            }

        }

    }


    @Override

    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

        super.onViewCreated(view, savedInstanceState);


        if (mParam1 != null) {


            Log.d("bear", "blankFragment mParam1 : " + mParam1);

        }

        if (mParam2 != null) {

            Log.d("bear", "blankFragment mParam2 : " + mParam2);

        }


        TextView fragment_Textview = view.findViewById(R.id.fragment_Textview);


        fragment_Textview.setText("   m    : " + mParam1 + "  ,   m " + mParam2);



    }



}







자바 제네릭 타입


단일 :

제네릭 타입은 타입을 파라미터(매개변수? 인자?)로 가지는 클래스와 인터페이스를 말한다. 


public class Box<T>{

private T t;

private T get(){return t}

private void set(T t){this.t = t}


}



복수 :

두개 이상의 멀티 타입 파라미터를 사용할 수 있는데, 각 타입 파마미터를 콤마로 구분한다.


public class Product<T, M>{


private T kind;

private M model;

public T getkind(){return this.kind;}

public M getModel(){return this.model;}


public void setKind(T kind ){ this.kind = kind;}

public void setModel(M model){this.model = model;}

}




'Java > study' 카테고리의 다른 글

Retrofit, RxJava, Android Project  (0) 2019.01.30
자바 분기문(break, continue)  (0) 2018.08.14
자바 반복문  (0) 2018.08.09
자바 제어문  (0) 2018.08.03
자바 자료형 종류  (0) 2018.07.26

+ Recent posts