问题描述
有没有办法让java方法接受不同类型的参数?
public class Test {
public boolean isTest(Type1 type1) {
do_something_with_type1
return bool;
}
public boolean isTest(DifferentType2 type2) {
do_something_with_type2
return bool;
}
}
在这种情况下,do_something_with_X
部分在两种方法之间是通用的。为了避免重复部分,我们应该有类似的东西:
public class Test {
public boolean isTest(Object obj) {
do_something_with_obj
return bool;
}
}
我们可以在 Java 中做到这一点吗?
解决方法
您可以通过多种方式实现这一目标。从您提到的示例开始,像 Object
类一样使用 List<?>
进行泛型管理。
Java 泛型可以以多种方式工作,在类级别、方法甚至方法参数上定义自己。
类级别的通用定义
class Example<T> {
public void foo(T type) {}
}
void usage() {
Example<String> example = new Example<>();
example.foo("Accepts strings");
}
方法类级别的泛型定义
class Example {
public <T> void foo(T type) {}
}
void usage() {
Example example = new Example();
example.foo("Accepts anything");
}
更复杂的泛型
您还可以指定规则使您的泛型更加严格。例如,作为某物的子类或父类。
public <T extends List> void foo(T type) {}
或
public <T extends Class<? super List>> void foo(T type) {}
甚至更远的地方,您可以指定泛型来扩展多个类类型:
public <T extends List & AutoCloseable> void foo(T type) {}
甚至更远的地方,您可以根据方法参数的泛型指定方法的返回类型。
public <R,T extends AutoCloseable & List<R>> R foo(T type) {
return null;
}
void usage() {
// Non existing class that implements AutoCloseable,List<T>
AutoCloseableArrayList<String> list;
// foo(T) will return String cause it's the generic of the parameter list
String s = foo(list);
}
,
您可以使用“do_something_with_obj”所需的方法创建一个接口,并在 type1 和 type2 中实现该接口。然后你可以将对象作为接口传递。
,如果不了解 do_something_with_x,真的很难说。我建议提取 do_something_with_x 以便您可以保留 isTest 方法的原始类型:
public class Test {
public boolean isTest(Type1 type1) {
doSomethingWithObject(type1);
return bool;
}
public boolean isTest(DifferentType2 type2) {
doSomethingWithObject(type2);
return bool;
}
private doSomethingWithObj(Object object) {
//do_something_with_object
}
}
,
好吧,你可能可以使用泛型
public class Test {
public <T> boolean isTest(T obj) {
do_something_with_obj
return bool;
}
}
接受一个 Object
作为参数是非常不寻常的,并不总是最好的选择......如果你可以编辑你关心的那两种类型(定义一个带有方法的接口),你可能想看看多态性你关心,让这两个类实现那个接口)
或者如果你不能,你可能想看看适配器设计模式,但如果你只需要一次就有点矫枉过正了
,不直接。
您可以创建一个 isTest(Object)
方法,但它会接受所有对象,从 Integer
到 String
到 Type1
到 Type2
。所以这是一个废话,不要选择那个。
但是有很多替代选择:
接口
如果 isTest
操作对 Type1
和 Type2
有意义,并且两者在 isTest 上有共享代码,但没有关系在 Type1
和 Type2
之间(没有共享超类型),感觉就像你搞砸了你的 API 设计。为什么 Type1 和 Type2 不共享一个接口或(抽象)类?
请注意,从 JDK16 开始,您可以“密封”接口,这意味着,在您枚举该接口的哪些实现存在的接口中,不允许其他代码实现它。意思是,你当然知道,在编译时。
因此,您可以制作一个接口并对其进行密封,以便只有 Type1
和 Type2
可以实现它,现在您可以确定并制作 isTest(ThatSharedInterface)
。
辅助方法
只需制作单独的 2 个 isTest
方法,并将共享代码放入帮助程序中。这可以很简单:
public boolean isTest(Type1 type1) {
return isTest0(type1);
}
public boolean isTest(Type2 type2) {
return isTest0(type2);
}
private boolean isTest0(Object o) {
...
}
这使用两个方面:
- 一般来说,挂钩到私有的实际实现的公共包装器的概念,以及辅助方法的概念,倾向于(按照惯例)使用
0
作为标记,此处使用. - 因为 isTest(Object) 方法是
private
,所以从 API 角度看,它是一种允许任何类型的灾难,这一事实不是问题。它是私密的:你知道用什么来称呼它。