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" first
和 second
。编译器会拒绝该代码,因为不能保证这两种类型兼容。
以下代码允许交换一个对象的 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"first
和second
。编译器会拒绝该代码,因为不能保证这两种类型兼容。