Android/Java 泛型全面详解 - 教程

1. 泛型的基本概念

什么是泛型?

泛型是Java 5引入的特性,允许在定义类、接口和方法时使用类型参数,提供编译时类型安全检查。

核心概念

// 泛型类
public class Container
<
T> {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
// 使用
Container<
String> stringContainer = new Container<
>();
stringContainer.setItem("Hello");
String value = stringContainer.getItem();
// 无需强制转换

2. 泛型语法详解

类型参数命名约定

  • T - Type(类型)
  • E - Element(元素,常用于集合)
  • K - Key(键)
  • V - Value(值)
  • N - Number(数字)
  • S, U, V - 第二、第三、第四类型

多类型参数

public class Pair
<
K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
// 使用
Pair<
String, Integer> pair = new Pair<
>("age", 25);

3. 泛型的使用场景

场景1:集合框架(最常用)

// 没有泛型(Java 5之前)
List list = new ArrayList();
list.add("hello");
list.add(123);
// 允许,但危险
String item = (String) list.get(0);
// 需要强制转换
// 使用泛型
List<
String> stringList = new ArrayList<
>();
stringList.add("hello");
// stringList.add(123); // 编译错误!
String item = stringList.get(0);
// 自动类型推断

场景2:Android RecyclerView Adapter

public abstract class BaseRecyclerAdapter
<
T, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
  protected List<
  T> dataList = new ArrayList<
  >();
  public void updateData(List<
  T> newData) {
  dataList.clear();
  dataList.addAll(newData);
  notifyDataSetChanged();
  }
  public void addItem(T item) {
  dataList.add(item);
  notifyItemInserted(dataList.size() - 1);
  }
  public T getItem(int position) {
  return dataList.get(position);
  }
  @Override
  public int getItemCount() {
  return dataList.size();
  }
  }
  // 具体实现
  public class UserAdapter
  extends BaseRecyclerAdapter<
  User, UserAdapter.ViewHolder> {
  static class ViewHolder
  extends RecyclerView.ViewHolder {
  TextView tvName, tvEmail;
  ViewHolder(View itemView) {
  super(itemView);
  tvName = itemView.findViewById(R.id.tv_name);
  tvEmail = itemView.findViewById(R.id.tv_email);
  }
  }
  @Override
  public void onBindViewHolder(ViewHolder holder, int position) {
  User user = getItem(position);
  holder.tvName.setText(user.getName());
  holder.tvEmail.setText(user.getEmail());
  }
  }

场景3:Retrofit网络请求

public interface ApiService {
@GET("users/{id}")
Call<
User> getUser(@Path("id") String id);
@GET("users")
Call<
List<
User>
> getUsers();
@POST("users")
Call<
ApiResponse<
User>
> createUser(@Body User user);
}
// 通用响应包装类
public class ApiResponse
<
T> {
private boolean success;
private String message;
private T data;
// getters and setters
}

场景4:ViewModel with LiveData

public class DataViewModel
<
T> extends ViewModel {
private MutableLiveData<
T> data = new MutableLiveData<
>();
private MutableLiveData<
String> error = new MutableLiveData<
>();
private MutableLiveData<
Boolean> loading = new MutableLiveData<
>();
public LiveData<
T> getData() {
return data;
}
public LiveData<
String> getError() {
return error;
}
public LiveData<
Boolean> getLoading() {
return loading;
}
protected void setData(T data) {
this.data.setValue(data);
loading.setValue(false);
}
protected void setError(String error) {
this.error.setValue(error);
loading.setValue(false);
}
protected void setLoading() {
loading.setValue(true);
}
}
// 具体实现
public class UserViewModel
extends DataViewModel<
List<
User>
> {
private UserRepository repository;
public UserViewModel() {
repository = new UserRepository();
}
public void loadUsers() {
setLoading();
repository.getUsers(new Callback<
List<
User>
>() {
@Override
public void onSuccess(List<
User> users) {
setData(users);
}
@Override
public void onError(String message) {
setError(message);
}
});
}
}

场景5:工具类和方法

public class CollectionUtils
{
// 泛型方法
public static <
T> boolean isEmpty(Collection<
T> collection) {
return collection == null || collection.isEmpty();
}
public static <
T> T getFirstItem(List<
T> list) {
return isEmpty(list) ? null : list.get(0);
}
public static <
T> List<
T> filter(List<
T> list, Predicate<
T> predicate) {
List<
T> result = new ArrayList<
>();
for (T item : list) {
if (predicate.test(item)) {
result.add(item);
}
}
return result;
}
}
// 使用
List<
User> users = // ... 获取用户列表
List<
User> activeUsers = CollectionUtils.filter(users, user -> user.isActive());

4. 通配符和边界

上界通配符 (? extends)

// 生产者,只能读取
public double sumNumbers(List<
? extends Number> numbers) {
double sum = 0;
for (Number number : numbers) {
sum += number.doubleValue();
}
return sum;
}
// 使用
List<
Integer> integers = Arrays.asList(1, 2, 3);
List<
Double> doubles = Arrays.asList(1.1, 2.2, 3.3);
double sum1 = sumNumbers(integers);
// 6.0
double sum2 = sumNumbers(doubles);
// 6.6

下界通配符 (? super)

// 消费者,只能写入
public void addNumbers(List<
? super Integer> list) {
for (int i = 1; i <= 5; i++) {
list.add(i);
}
}
// 使用
List<
Number> numbers = new ArrayList<
>();
List<
Object> objects = new ArrayList<
>();
addNumbers(numbers);
// 可以
addNumbers(objects);
// 可以

无界通配符 (?)

// 当你只关心集合操作而不关心具体类型时
public void processList(List<
?> list) {
System.out.println("List size: " + list.size());
for (Object item : list) {
System.out.println(item.toString());
}
}

5. 泛型的优点

1. 类型安全

// 编译时类型检查
List<
String> names = new ArrayList<
>();
names.add("Alice");
// names.add(123); // 编译错误!
// 运行时不会出现ClassCastException
String name = names.get(0);
// 安全

2. 代码复用

// 一个泛型类处理多种类型
public class Repository
<
T> {
public void save(T entity) {
/* 通用保存逻辑 */
}
public T findById(String id) {
/* 通用查询逻辑 */
}
}
// 用于不同实体
Repository<
User> userRepo = new Repository<
>();
Repository<
Product> productRepo = new Repository<
>();

3. 消除强制转换

// 之前
List list = new ArrayList();
list.add("hello");
String value = (String) list.get(0);
// 需要强制转换
// 使用泛型
List<
String> list = new ArrayList<
>();
list.add("hello");
String value = list.get(0);
// 自动类型推断

4. 更好的API设计

// 清晰的接口契约
public interface Cache<
K, V> {
void put(K key, V value);
V get(K key);
void remove(K key);
}
// 实现
public class MemoryCache
<
K, V> implements Cache<
K, V> {
private Map<
K, V> cache = new HashMap<
>();
@Override
public void put(K key, V value) {
cache.put(key, value);
}
@Override
public V get(K key) {
return cache.get(key);
}
@Override
public void remove(K key) {
cache.remove(key);
}
}

6. 泛型的缺点和限制

1. 类型擦除

// 编译时泛型信息会被擦除
List<
String> stringList = new ArrayList<
>();
List<
Integer> integerList = new ArrayList<
>();
// 运行时都是List,无法区分
System.out.println(stringList.getClass() == integerList.getClass());
// true
// 无法使用instanceof检查泛型类型
// if (obj instanceof List<String>) // 编译错误

2. 无法创建泛型数组

// 编译错误
// T[] array = new T[10];
// 解决方案
@SuppressWarnings("unchecked")
public <
T> T[] createArray(Class<
T> clazz, int size) {
return (T[]) Array.newInstance(clazz, size);
}

3. 无法实例化类型参数

public class Factory
<
T> {
public T createInstance() {
// return new T(); // 编译错误
// 解决方案:使用Class对象和反射
try {
return clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

4. 静态上下文的限制

public class GenericClass
<
T> {
private T instance;
// 编译错误:不能使用类型参数T
// private static T staticField;
// 编译错误:静态方法不能使用类的类型参数
// public static T getStaticInstance() { return null; }
// 但可以定义泛型静态方法
public static <
U> U staticMethod(U param) {
return param;
}
}

7. 最佳实践

1. 优先使用泛型集合

// 好的做法
List<
String> names = new ArrayList<
>();
Map<
String, Integer> scores = new HashMap<
>();
// 避免使用原始类型
List rawList = new ArrayList();
// 不要这样用

2. 使用有意义的类型参数名

// 好的命名
public interface Repository<ENTITY, ID> {
  ENTITY findById(ID id);
  void save(ENTITY entity);
  }
  // 避免模糊的命名
  public interface Repository<
  T, U> {
  // 不清晰
  T findById(U id);
  }

3. 合理使用通配符

// PECS原则:Producer Extends, Consumer Super
public void copy(List<
? extends Number> src, List<
? super Number> dest) {
for (Number number : src) {
dest.add(number);
}
}

4. 处理类型擦除

// 使用Class对象保留类型信息
public class TypeSafeRepository
<
T> {
private final Class<
T> entityClass;
private List<
T> data = new ArrayList<
>();
public TypeSafeRepository(Class<
T> entityClass) {
this.entityClass = entityClass;
}
public T createInstance() throws Exception {
return entityClass.newInstance();
}
public boolean isInstance(Object obj) {
return entityClass.isInstance(obj);
}
}

8. Android中的特殊考虑

1. Parcelable泛型处理

public class GenericParcelable
<
T extends Parcelable> implements Parcelable {
private T data;
protected GenericParcelable(Parcel in) {
// 需要额外的类型信息来处理泛型
Class<
T> clazz = (Class<
T>) in.readSerializable();
data = in.readParcelable(clazz.getClassLoader());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeSerializable(data.getClass());
dest.writeParcelable(data, flags);
}
}

2. ViewBinding泛型

public abstract class BaseFragment
<
B extends ViewBinding> extends Fragment {
protected B binding;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = createBinding(inflater, container);
return binding.getRoot();
}
protected abstract B createBinding(LayoutInflater inflater, ViewGroup container);
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
// 具体实现
public class HomeFragment
extends BaseFragment<
FragmentHomeBinding> {
@Override
protected FragmentHomeBinding createBinding(LayoutInflater inflater, ViewGroup container) {
return FragmentHomeBinding.inflate(inflater, container, false);
}
}

总结

使用泛型的情况:

  • ✅ 集合类操作
  • ✅ 通用工具类和组件
  • ✅ API接口设计
  • ✅ 需要类型安全的场景
  • ✅ 代码复用的需求

避免泛型的情况:

  • ❌ 简单的类型标识
  • ❌ 性能关键的底层代码
  • ❌ 需要运行时类型信息的场景
  • ❌ 过度复杂的类型层次
posted @ 2025-09-08 09:30  yfceshi  阅读(20)  评论(0)    收藏  举报