Java中限制泛型的有界类型

Java 是一种多功能且功能强大的编程语言,以其强大的类型系统而闻名。增强类型安全性和促进代码可重用性的关键功能之一是有界类型(Bounded Type)。

有界类型允许开发人员对可用作类、接口和方法中的泛型参数的类型施加约束。通过定义这些约束,开发人员可以确保支持某些操作并防止编译时出现错误。在本文中,我们将深入研究 Java 中的有界类型,并探讨如何利用它们来编写更健壮、更灵活的代码。

在 Java 中,有界类型是指对可用作泛型类或方法中的类型参数的类型指定约束。有界类型用于限制可以使用的类型范围,提供有关可接受类型的更具体的信息。

在 Java 中,泛型类型广泛用于创建可重用组件。它们允许开发人员定义可以在各种不同类型上操作的类、接口和方法,而无需牺牲类型安全性。但是,在某些情况下,有必要限制可用作泛型参数的类型范围。这就是有界类型发挥作用的地方。

有界类型参数是仅限于特定类型子集的泛型类型。可以使用 extends 关键字后跟上限来定义它。上限可以是类或接口,它指示泛型类型必须是指定类的子类或实现指定接口。

定义有界类型参数的语法如下:

class MyClass<T extends MyClassType> {  
    // ...  
}  

在上例中,T 是类型参数,MyClassType 是上界。这意味着任何用作参数的 T 类型都必须是 MyClassType 或它的子类。

Java 中有两种类型的界限:上限和下限。

上界通配符:

  • 使用关键字指定上限extends。
  • 它将允许的类型限制为特定类型或其任何子类型。

public class Box<T extends Number> {
    //  带有类型参数 T 上限的类定义
}

在此示例中,T可以是 的子类的任何类型Number。

下界通配符:
使用关键字指定下限super。
它将允许的类型限制为特定类型或其任何超类型。

public void addNumbers(List<? super Integer> list) {
    // 接受整数或其超类列表的方法
}

在此示例中,该addNumbers方法可以接受ListofInteger或 的任何超类型Integer。

这是一个更详细的示例,说明了上限和下限:


public class BoundedTypesExample {

    // Upper Bounded Wildcard
    public static <T extends Number> double sumOfListUpperBound(List<T> list) {
        double sum = 0.0;
        for (T number : list) {
            sum += number.doubleValue();
        }
        return sum;
    }

   
// Lower Bounded Wildcard
    public static void addIntegers(List<? super Integer> list) {
        for (int i = 1; i <= 5; i++) {
            list.add(i);
        }
    }

    public static void main(String[] args) {
        List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);

       
// Upper Bounded
        double sum = sumOfListUpperBound(integers);
        System.out.println(
"Sum of integers: " + sum);

        List<Number> numbers = new ArrayList<>();
        addIntegers(numbers);

        System.out.println(
"List of numbers: " + numbers);
    }
}

在此示例中,sumOfListUpperBound 接受任何属于 Number 子类的 List 类型,而 addIntegers 则接受 Integer List 或 Integer 的任何超类型。

有界类型示例:
为了更好地理解有界类型,让我们考虑几个示例。假设我们有一个代表不同类型形状的类层次结构:

class Shape {  
    // ...  
}  
class Circle extends Shape {  
   
// ...  
}  
class Rectangle extends Shape {  
   
// ...  
}  
现在,让我们定义一个名为 ShapeContainer 的通用类,它可以容纳各种形状的对象:
class ShapeContainer<T extends Shape> {  
    private T shape;  
    public void addShape(T shape) {  
        this.shape = shape;  
    }  
    public T getShape() {  
        return shape;  
    }  
}  

在本示例中,ShapeContainer 类的有界类型参数 T 的上界为 Shape。

通过使用有界类型,我们可以执行编译时类型安全,并确保只能对存储在 ShapeContainer 中的对象执行与形状相关的操作。例如,如果我们尝试添加字符串或任何其他不相关的类型,编译器将生成错误。


具有多个边界的有界类型
Java 还支持具有多个边界的有界类型,其中一个类型参数必须满足多个约束条件。使用 & 符号指定多个边界,后面跟接口或类名。

下面是一个比较两个对象的泛型方法示例:

class BoundedTypeExample {  
    public static <T extends Comparable<T> & MyInterface> int compare(T obj1, T obj2) {  
        return obj1.compareTo(obj2);  
    }  
}  

在本例中,泛型方法 compare 的有界类型参数 T 有两个界:Comparable<T> 和 MyInterface。它确保类型参数 T 必须实现 Comparable 接口并扩展 MyInterface 接口。

通过使用具有多个边界的有界类型,我们可以利用多个接口或类的功能来提供更灵活、更强大的功能。

下面是一个完整的 Java 程序,演示了如何使用带输入和输出的有界类型:

// Shape hierarchy  
abstract class Shape {  
    public abstract void draw();  
}  
class Circle extends Shape {  
    @Override  
    public void draw() {  
        System.out.println(
"Drawing a circle");  
    }  
}  
class Rectangle extends Shape {  
    @Override  
    public void draw() {  
        System.out.println(
"Drawing a rectangle");  
    }  
}  
// Generic class with bounded type parameter  
class ShapeContainer<T extends Shape> {  
    private T shape;  
    public void addShape(T shape) {  
        this.shape = shape;  
    }  
    public T getShape() {  
        return shape;  
    }  
}  
// Main class  
public class BoundedTypeExample {  
    public static void main(String[] args) {  
       
//为圆形创建 ShapeContainer  ;
        ShapeContainer<Circle> circleContainer = new ShapeContainer<>();  
        Circle circle = new Circle();  
        circleContainer.addShape(circle);  
       
// Get the shape from the container  
        Circle retrievedCircle = circleContainer.getShape();  
        retrievedCircle.draw();  
       
// 为矩形创建一个 ShapeContainer  ;
        ShapeContainer<Rectangle> rectangleContainer = new ShapeContainer<>();  
        Rectangle rectangle = new Rectangle();  
        rectangleContainer.addShape(rectangle);  
       
// 从容器中获取形状  ;
        Rectangle retrievedRectangle = rectangleContainer.getShape();  
        retrievedRectangle.draw();  
       
// 尝试在 ShapeContainer 中添加字符串(编译时出错) ;
       
// ShapeContainer<String> stringContainer = new ShapeContainer<>(); // Compile-time error  
       
// stringContainer.addShape("Invalid Shape"); // Compile-time error  
    }  
}  

Java 中的有界类型提供了一种强大的机制,可对通用类型实施约束,确保类型安全并促进代码重用。通过指定上限,开发人员可以限制可用作泛型参数的类型范围,从而提高代码的健壮性和可维护性。无论是在类层次结构中限制类型,还是从多个接口施加约束,有界类型都能让开发人员编写出更具表现力和更可靠的代码。

通过了解并有效利用有界类型,Java 开发人员可以充分发挥语言类型系统的潜力,构建高质量的软件系统。