Java 为泛型函数强制执行相同类型(最佳实践)

Java 为泛型函数强制执行相同类型(最佳实践),java,generics,methods,Java,Generics,Methods,我有一个泛型函数,它接收两个类型相同的参数 到目前为止,函数如下所示: void <T> copyTo1(Class<T> type, T destination, T source) { // Do stuff } copyTo1(Object.class, new Object(), new Object()); // Okay copyTo1(Object.class, new Object(), new String()); // Okay copyTo

我有一个泛型函数,它接收两个类型相同的参数

到目前为止,函数如下所示:

void <T> copyTo1(Class<T> type, T destination, T source) {
    // Do stuff
}
copyTo1(Object.class, new Object(), new Object()); // Okay
copyTo1(Object.class, new Object(), new String()); // Okay
copyTo1(Object.class, new String(), new Object()); // Okay
copyTo1(String.class, new String(), new String()); // Okay
copyTo1(String.class, new String(), new Date()); // Not okay

copyTo2(new Object(), new Object()); // Okay
copyTo2(new Object(), new String()); // Okay
copyTo2(new String(), new Object()); // Not okay
copyTo2(new String(), new Date()); // Not okay
第二种选择更具限制性,这对我来说非常好

现在的问题是:应该选择哪种方法?还是有另一个我没看到的

非常感谢


仅供记录:我知道我可以像这样定义和使用函数

void copyTo(T目的地,T来源){
//做事
}
...
这copyTo(新字符串(),新字符串());

但我希望用户立即看到他正在尝试的操作何时不被允许。当他解释类型的定义时,情况并非如此。

问题是“应该属于同一类型”的确切含义是什么?Java中的所有引用都是
对象的实例
,因此根据定义,它们总是“同一类型”。由于任何引用类型都是
对象的子类型
,因此它应该是:

void copyTo2(Object destination, Object source)

Java中的泛型类型参数旨在提供约束,以便您可以在不使用强制转换的情况下执行某些操作。但是,在这种情况下,您对类型参数没有任何限制,因此您不能依赖类型
T
来执行任何操作,除了
Object

中提供的内容之外,这不是关于最佳实践,而是关于需求。您希望在
目标
之间建立什么样的关系,请相应地使用类型参数。@RohitJain我同意,请选择最适合的类型。如果限制性更强的方法有效,那就去做吧!我忘了提到在具体实现中,
type
将不被使用。我更喜欢第二个选项,但这最终是一个具体要求的问题。@LeonardBrünings我选择了第二个版本。函数应该从同一类的另一个实例的一个实例复制属性。有点像BeanUtils.copyProperties,但更简单(无需转换)并忽略空值。由于我们要传输特定于类的属性,所以传递两种不同类型的属性是没有意义的,因为它们只有
对象
作为共同祖先。@Zeeker:但是您对参数的类型一无所知,所以除非使用反射,否则如何访问“属性”?如果使用反射,则无论如何都没有类型安全性。泛型用于类型安全,并且除了类型
Object
的两个参数之外,再也无法获得类型安全。您的需求是矛盾的,因为“传递两个不同的类型,它们只有对象作为共同祖先”传递的是“相同类型”的两个东西,因为该类型可以是
对象
,并且任何引用类型都可以隐式转换为
对象
。耶,我使用反射来访问对象的属性。当然,我们可以将
对象的属性
复制到
对象
,但这有什么用呢?我可以看到并理解这种混淆,但通过使用泛型,我至少可以确保传递的参数不只是将
Object
作为公共祖先,因此复制属性实际上是有意义的。@Zeeker:“但通过使用泛型,我至少可以确保传递的参数不只是将对象作为公共祖先,所以复制属性实际上是有意义的。“不,你不能。我可以。在第二个版本中,如果将日期对象作为第一个参数传入,则只能传入第二个参数,即日期本身或日期的子类,这意味着第二个参数中的所有日期属性都会复制到第一个参数中,这是无法绕过的。若我只允许两个任意对象,那个么我就可以传递字符串和日期,复制就并没有任何意义了。
void <T> copyTo(T destination, T source) {
    // Do stuff
}

...

this.<String> copyTo(new String(), new String());
void copyTo2(Object destination, Object source)