Middle
Where have you used generics in your development experience?
sobes.tech AI
Answer from AI
Used generics:
- For implementing type-safe collections. For example,
ArrayList<MyObject>instead of rawArrayList, which prevents runtime errors related to type casting.// Non-type-safe approach (raw type) List list = new ArrayList(); list.add("String"); list.add(123); // Adding int // Type-safe approach with generics List<String> stringList = new ArrayList<>(); stringList.add("String"); // stringList.add(123); // Compiler will give an error - For creating universal RecyclerView adapters. Allows reusing adapter logic for different data types.
// Example of a universal ViewHolder class GenericViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(item: T) { // Data binding logic depending on type T } } // Example of a universal adapter class GenericAdapter<T>(private val items: List<T>) : RecyclerView.Adapter<GenericViewHolder<T>>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GenericViewHolder<T> { // Create ViewHolder } override fun onBindViewHolder(holder: GenericViewHolder<T>, position: Int) { holder.bind(items[position]) } override fun getItemCount() = items.size } - When creating object factories. To obtain a specific object type without explicit casting.
interface Factory<T> { T create(); } class StringFactory implements Factory<String> { @Override public String create() { return "New String"; } } class IntegerFactory implements Factory<Integer> { @Override public Integer create() { return 100; } } Factory<String> stringFactory = new StringFactory(); String myString = stringFactory.create(); // Get String without casting - To constrain types in methods and classes. Using bounded generics (
<T extends MyInterface>or<T super MyClass>) to ensure the generic type implements a certain interface or inherits from a specific class.// Method that accepts a list of elements implementing Serializable public <T extends Serializable> void saveObjectList(List<T> list) { // Saving logic } - In architectural components. For example, when working with LiveData or ViewModel, generics are often used to define the data type they manage.
// LiveData for a list of objects of a specific type val myData: LiveData<List<MyItem>> = // initialization // ViewModel with data of a specific type class MyViewModel : ViewModel() { val data: MutableLiveData<MyStateType> by lazy { MutableLiveData<MyStateType>() } } - When developing network clients. For automatic deserialization of server responses into specific object types.
// Example of a Retrofit service with generics in response interface ApiService { @GET("users") Call<List<User>> getUsers(); @GET("products/{id}") Call<Product> getProduct(@Path("id") String productId); }
Generics significantly increased type safety, readability, and code reusability.