Java - 泛型;如果你想交换一个对象的 2 个项目,参数化一个方法有用吗?

Java - Generics; Is it usefull to parameterize a method if you want to swap 2 Items of an object?

以下代码允许交换一个对象的 2 个项目:

public class Box<F, S> {
    F first;
    S second;   

    //Method to swap
    public static <F> void swapItems(Box<F,F> box){

        F temp = box.first;
        box.first = box.second;
        box.second = temp;
    }
}

//The method could also be implemented like this:

    void swapItems() {

        F tmp1 = first;
        S tmp2 = second;
        first = (F) tmp2;
        second = (S) tmp1;
    }

通用代码有什么优势?我只是不明白。 有人能给我解释一下吗?如果我在 2 个对象上调用此方法,通用方法是否有用?

在很多情况下,这实际上甚至无法编译。举一个更具体的例子,假设你的类型 F 是一个字符串,而你的类型 S 是一个整数。然后,您将得到这样的 swapItems 方法:

public void swapItems(){
    String first = "foo";
    Integer second = 2;
    String tmp1 = first;
    Integer tmp2 = second;
    first = (String) tmp2;
    second = (Integer) tmp1;
}

编译器会报错:"Inconvertible types; cannot cast java.lang.Integer to java.lang.String".

The method could also be implemented like this:

不,不能。如果你交换 Box<F, S> 你会得到 Box<S, F>,另一种类型。使用实例方法,您不能神奇地更改调用它的对象的类型!

Box<F,S> 更改为 Box<S, F> 的静态方法可能是这样的:

public static <F, S> Box<S, F> swapItems(Box<F,S> box){

    Box<S, F> newBox = new Box<>();
    newBox.first = box.second;
    newBox.second = box.first;
    return newBox;
}

// usage:
Box<Integer, String> newBox = Box.swapItems(someBox);

实例方法还是可以写的,但是需要return一个新的框而不是改变this的状态。

public Box<S, F> itemsSwapped(){

    Box<S, F> newBox = new Box<>();
    newBox.first = this.second;
    newBox.second = this.first;
    return newBox;
}

// usage:
Box<Integer, String> newBox = someBox.itemsSwapped();

你的例子class实际上是一个错误使用泛型的好例子。用于交换物品的通用 Box 是建立在误解之上的。

Might the generic one be useful if i call this method on 2 objects?

没错(问题中的代码)。泛型不是为代码重用或结构化代码而设计的。我们有方法、包和模块。

支持交换顺序的两个项目的盒子,可能会更好地实现如下(虽然更合适的名称应该是 Pair,我相信):

class Box<T> {
    private T first;
    private T second;   

    //2-parameter constructor

    public void swapItems(){

        T temp = first;
        first = second;
        second = temp;
    }

    //getters and setters
}

上面的class可以这样使用:

Box<String> stringBox = new Box<>("first", "second");
String first = stringBox.getFirst();
String second = stringBox.getSecond();

或如下:

Box<Integer> intBox = new Box<>(1, 2);
int first = intBox.getFirst();
int second = intBox.getSecond();

What is the advantage of the generic code?

假设你有一个像上面那样的class,那么泛型将允许你制作一个不同类型的盒子<T>,编译器保证类型安全,就像在这两个示例使用: Box class 被定义一次,但与不同类型的 "box items" 一起使用,编译器知道这些类型并帮助验证类型。

例如,以下不正确的调用将失败(继续上面的示例):

String third = intBox.getFirst();

最后一个(不正确的)语句将在编译时失败,从而实现更快的反馈(与 class 在运行时抛出异常相反)。

其他重要说明:

  • 您的 class 声明了两个不同的类型参数 <F, S>,因此您不能 "swap" firstsecond。编译器会拒绝该代码,因为不能保证这两种类型兼容。