简体   繁体   中英

Is there any way to check if sub class has passed generic type argument?

I have a super class (Android's Fragment):

public abstract class BaseFragment<T> extends Fragment {

    private T mListener;

    public T getFragmentInteractionListener(){
        return mListener;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        castFragmentInteractionListener();
    }

    void castFragmentInteractionListener(){         
        Type superClassType = this.getClass().getGenericSuperclass();
        if (superClassType instanceof ParameterizedType) {
            try {
                // I want to know if there is any way to check if the type argument has 
                // been set? So I can avoid the exception.
                Class<T> listenerClazz = (Class<T>) ((ParameterizedType) superClassType).getActualTypeArguments()[0];

                mListener = FragmentUtils.castFragmentInteractionListener(context, this, listenerClazz);

            } catch (Exception e) {

            }
        }

    }
}

and some sub classes derived from it.

public class FragmentDoesNotNeedListener extends BaseFragment {


}

public class FragmentHasListener extends BaseFragment<FragmentInteractionListener> {

    interface FragmentInteractionListener {
        void onClick();
        void onExit();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getFragmentInteractionListener().onClick();

    }

}

Essentially, I want each fragment to derive from the BaseFragment , most of them have the listener that can be called from themselves. I don't want to repeat the code to cast it, therefore create the base fragment and use generic type. However, some of the fragments do not need to use listener. But I don't how to check if the argument type is given or not.

In BaseFragment class, the method castFragmentInteractionListener casts the class to a class field, and then uses it to cast the class into the listener. It is OK if the child class ( FragmentDoesNotNeedListener ) does not pass the generic type argument because the exception will be caught. However, I wonder if there is any way to check instead of catching the exception? Or maybe this is not a good design...

According to this StackOverflow post

Generic informations are erased at runtime , it cannot be recovered. A workaround is to pass the class T in parameter of a static method :

public class MyGenericClass {

 private final Class<T> clazz; public static <U> MyGenericClass<U> createMyGeneric(Class<U> clazz) { return new MyGenericClass<U>(clazz); } protected MyGenericClass(Class<T> clazz) { this.clazz = clazz; } public void doSomething() { T instance = clazz.newInstance(); } } 

It's ugly, but it works.

Or you could simply perform checks on which class you are in fact using

public abstract class BaseFragment<T> extends Fragment {

//...

public static Class classType(Class cls)
        {
            if(cls.equals(FragmentDoesNotNeedListener.class))
                return FragmentDoesNotNeedListener.class;
            else
                if (cls.equals(FragmentHasListener.class))
                    return FragmentHasListener.class;
            //else
              //  if(....)

            else
                return null;
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM