这是一个非常简单的示例:
private boolean f(List x) {
return x != null && !x.isEmpty();
}
private boolean f(Map x) {
return x != null && !x.isEmpty();
}
两个函数中的代码相同,它们只是在不同的对象上操作。我想将它们合并为一个函数,以避免代码重复。
我尝试了以下方法:
private <T> boolean f(T x) {
return x != null && !x.isEmpty();
}
但是它给x.isEmpty()
答案 0 :(得分:13)
两个类都实现的接口覆盖了要使用的部分时,请使用该接口。
但是在您的情况下,$a[0]= "google";
$a[1]= "yahoo";
$a[2]= "Bing";
$b= "Bing is Good";
strpos($b, $a[0]); // false
strpos($b, $a[1]); // false
strpos($b, $a[2]); // true as Bing found
和List
不共享提供Map
的接口,因此您可以选择:
重载(以下代码不变)
isEmpty
接受private boolean f(List x) {
return x != null && !x.isEmpty();
}
private boolean f(Map x) {
return x != null && !x.isEmpty();
}
并使用Object
分支
instanceof
接受private boolean f(Object x) {
// (roughly)
if (x == null) {
return false;
}
if (x instanceof List) {
return !((List)x).isEmpty();
}
if (x instanceof Map) {
return !((Map)x).isEmpty();
}
throw new IllegalArgumentException(); // Or whatever
}
并使用反射来获取Object
方法(如果有)并调用它
isEmpty
在这些方法中,重载对我来说似乎是最干净的方法,这尤其重要,因为如果您尝试在其中使用private boolean f(Object x) {
// (roughly)
try {
return x != null && !(boolean)x.getClass().getMethod("isEmpty").invoke(x);
} catch (Exception e) {
throw new IllegalArgumentException(); // Or whatever
}
}
,则会给您一个编译时错误一种无法处理的类型(而其他类型则是运行时错误,很容易出错),但这(至少是轻微的)是一种见解。
答案 1 :(得分:3)
您想使用一个共同的祖先接口来多态地同时引用列表和地图,但遗憾的是不存在。由于Java是严格类型化的,因此编译器正在寻找与该签名匹配的方法定义,该签名无法找到。
您不能完全按照要求的方式来做。
看看Apache commons如何使用instanceof
将此类型转换为相关类型org.apache.commons.collections.CollectionUtils#sizeIsEmpty
public static boolean sizeIsEmpty(Object object) {
if (object instanceof Collection) {
return ((Collection) object).isEmpty();
} else if (object instanceof Map) {
return ((Map) object).isEmpty();
} else if (object instanceof Object[]) {
return ((Object[]) object).length == 0;
} else if (object instanceof Iterator) {
return ((Iterator) object).hasNext() == false;
} else if (object instanceof Enumeration) {
return ((Enumeration) object).hasMoreElements() == false;
} else if (object == null) {
throw new IllegalArgumentException("Unsupported object type: null");
} else {
try {
return Array.getLength(object) == 0;
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
}
}
}
答案 2 :(得分:1)
您可以尝试以下操作:
private Object boolean f(Object x) {
if (x instanceof List) {
List l = (List)x;
return !l.isEmpty();
} else if (x instanceof Map) {
Map m = (Map)x;
return !m.isEmpty();
}
return false;
}
答案 3 :(得分:1)
由于isEmpty()
并非从公共接口继承而来,所以您不能做到。一种解决方法是接受确定为空的谓词:
private static <T> boolean isNonEmpty(T value, Predicate<T> isEmpty) {
return value != null && !isEmpty.test(value);
}
样品使用:
isNonEmpty(Arrays.asList(1, 2, 3), List::isEmpty)
isNonEmpty(new HashMap<>(), Map::isEmpty)
isNonEmpty("foo", String::isEmpty)
可以说,这种辅助方法并不是全部有用。
答案 4 :(得分:0)
自从标记了java-8以来,您就可以成为Optional类。
public class BaseController : Controller
{
public ApplicationDbContext _db;
public BaseController(ApplicationDbContext db)
{
_db = db;
ViewData["MyKey"] = _db.MyTable.ToList();
}
}
一些例子:
private static boolean isEmpty(Optional<Collection> collection){
return collection.map(Collection::isEmpty).orElse(false);
}
输出:
public static void main(String[] args) {
ArrayList arrayList = null;
System.out.println(isEmpty(Optional.ofNullable(arrayList)));
Map map = null;
//Convert Map entries to entryset (Collection) via Optional::map
System.out.println(isEmpty(Optional.ofNullable(map).map(Map::entrySet)));
}
答案 5 :(得分:0)
我喜欢T.J.Crowder's answer中的第3点,但是我会使用稍微不同的方法(并且速度更快):
private static boolean f(Object x) {
MethodType methodType = MethodType.methodType(boolean.class);
Lookup l = MethodHandles.lookup();
try {
MethodHandle handle = l.findVirtual(x.getClass(), "isEmpty", methodType);
return (boolean) handle.invoke(x);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}