泛型方法
泛型方法允许在方法签名中声明类型参数,从而创建可以处理多种数据类型的灵活方法。
实际案例:
假设有一个方法需要比较两个对象的某个属性是否相等。由于这个比较逻辑是通用的,可以使用泛型方法来避免为每个类型重复编写相同的代码。
public static boolean compareById(T obj1, T obj2, Function idGetter) {
return idGetter.apply(obj1).equals(idGetter.apply(obj2));
}
// 使用Lambda表达式作为idGetter
boolean areEqual = compareById(employee1, employee2, Employee::getId);
// 假设Employee接口有一个getId()方法返回Integer类型的ID
泛型类
泛型类允许创建可以处理多种数据类型的类。
实际案例:
可以创建一个泛型类来表示缓存,该缓存可以存储任何类型的键值对。
public class Cache {
private Map cacheMap = new HashMap<>();
public V get(K key) {
return cacheMap.get(key);
}
public void put(K key, V value) {
cacheMap.put(key, value);
}
// 其他方法...
}
// 使用泛型类
Cache employeeCache = new Cache<>();
employeeCache.put("123", new Engineer());
Employee employee = employeeCache.get("123");
使用泛型集合
在Java中,使用泛型集合(如ArrayList
实际案例:
假设有一个应用程序需要处理不同类型的员工(如工程师、经理等),可以创建一个通用的Employee接口和几个实现该接口的类。然后,使用List
interface Employee {
String getName();
// 其他方法...
}
class Engineer implements Employee {
// 实现接口方法...
}
class Manager implements Employee {
// 实现接口方法...
}
// 使用泛型集合
List employees = new ArrayList<>();
employees.add(new Engineer());
employees.add(new Manager());
for (Employee employee : employees) {
System.out.println(employee.getName());
}
类型参数约束
泛型类或接口可以通过extends关键字约束类型参数,确保只接受特定类型或其子类。
案例:
public class Pair<T extends Comparable> {
private T first;
private T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public int compareTo(Pair other) {
return this.first.compareTo(other.first);
}
}
在这个例子中,Pair类的类型参数T被约束为实现了Comparable
通配符和边界
在泛型中,我们可以使用通配符(?)和边界(extends 和 super)来创建更灵活的泛型代码。
实际案例:
假设有一个方法需要处理实现了某个特定接口的多个集合,可以使用通配符和边界来定义这个方法。
public void processAll(Collection extends employee> employees) {
for (Employee employee : employees) {
// 处理每个员工...
}
}
// 使用方法
List engineers = new ArrayList<>();
processAll(engineers); // 合法,因为Engineer是Employee的子类型
泛型与继承
当使用泛型类时,子类可以继承泛型父类,并提供具体的类型参数。这允许创建具有特定类型限制的子类。
实际案例:
假设有一个泛型类NumberList
public class NumberList extends ArrayList {
// 特定于NumberList的方法...
}
public class IntegerList extends NumberList {
// IntegerList特有的方法(如果有的话)...
}
// 使用IntegerList
IntegerList integers = new IntegerList();
integers.add(1);
integers.add(2);
// ...
类型擦除与反射的结合
虽然泛型在编译后会经历类型擦除,但通过反射可以动态地获取类型信息,实现某些特定需求。
案例:
public class GenericReflectionExample {
public static void printGenericType(Class> clazz) throws NoSuchFieldException {
Field field = clazz.getDeclaredField("value");
ParameterizedType genericType = (ParameterizedType) field.getGenericType();
System.out.println("泛型类型是:" + genericType.getActualTypeArguments()[0]);
}
public static class Container {
private T value;
public Container(T value) {
this.value = value;
}
}
public static void main(String[] args) throws Exception {
GenericReflectionExample.printGenericType(GenericReflectionExample.Container.class);
}
}
这个例子通过反射获取Container类中字段value的泛型类型信息,展示了在类型擦除后如何仍然能够访问泛型类型参数。
通过上述技巧与案例,可以看到泛型在面向对象编程中的广泛应用,不仅提升了代码的健壮性,还极大地增强了程序的灵活性和扩展性。
本文暂时没有评论,来添加一个吧(●'◡'●)