我的动机是创建一组名为toString()的重载函数,它接受任何对象(或者至少是我感兴趣的对象)并创建一个对调试有用的字符串。然后我也想要一个out()方法,而不必重新创建相同(繁琐)的重载。
我看到我用这段代码得到的是out()中的toString(e)总是调用toString(Object)。在研究泛型之后,我无法看到这种方法。因此,如果有人能够了解如何做到这一点,我将不胜感激。
总结一下:
这可以用泛型来完成吗?
public class A3 {
static <E> void out(E e){
System.out.println(toString(e));
}
static String toString(Object o){
return "Object";
}
static String toString(String str){
return "String";
}
static String toString(Integer i){
return "Integer";
}
static String toString(SomeObject o){
return "A description of the object";
}
public static void main(String[] args) {
out("");
out(1);
}
}
答案 0 :(得分:3)
在编译时确定调用哪个方法。如果你想要动态检查,你必须自己编写代码。
唯一的方法是使用一串if
和instanceof
支票。
static <E> void out(E e){
Object o = e instanceof String ? toString((String) e) :
e instanceof Integer ? toString((Integer) e) :
toString(e);
System.out.println(o);
}
或者更好的选择是实施
static String toString(Object o) {
return o instanceof String ? "String" :
o instanceof Integer ? "Integer" :
"Object";
}
注意:除非您这样做,否则toString((Object) "hello")
将返回&#34;对象&#34;
答案 1 :(得分:3)
可能有多种方法可以实现实际想要实现的目标。根据您提到的代码和约束,可能有多种方法可以实现您想要实现的目标。但着眼于这一点:
是否有一种优雅的方法来实现out()方法,利用toString()的退出重载。
为了利用这些方法,您必须调度到所需的方法。该方法必须在编译时已知,或者在运行时根据给定对象的类型确定。但是,这不能基于泛型和语言内部method overload resolution来完成,因为在编译期间,泛型参数基本上被Object
替换。
解决此问题的一种方法是在公共地图中为所需的Function
方法注册toString
,并在运行时查找这些函数。
请注意,这不一定是您实际想要做的“好”解决方案,而是以一种通用且易于扩展的方式显示“利用现有的过载”的一种方式。
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
public class GenericToString
{
private static final Map<Class<?>, Function<?, String>>
TO_STRING_FUNCTIONS = new LinkedHashMap<>();
private static <C> void register(Class<C> c, Function<C, String> f)
{
TO_STRING_FUNCTIONS.put(c, f);
}
static
{
register(Object.class, x -> toString(x));
register(String.class, x -> toString(x));
register(Integer.class, x -> toString(x));
}
public static void main(String[] args)
{
out("x");
out(1);
out(1.0);
}
static void out(Object object)
{
System.out.println(toStringDispatcher(object));
}
static String toString(Object o)
{
return "Object: "+o;
}
static String toString(String s)
{
return "String: "+s;
}
static String toString(Integer i)
{
return "Integer: "+i;
}
private static String toStringDispatcher(Object object)
{
if (object == null)
{
return "null";
}
Function<?, String> f = TO_STRING_FUNCTIONS.get(object.getClass());
if (f != null)
{
@SuppressWarnings("unchecked")
Function<Object, String> g = (Function<Object, String>)f;
return g.apply(object);
}
return toString(object);
}
}
答案 2 :(得分:1)
你必须使用反射来实现这个目标(如果你可以使用它),
Method method = A3.class.getDeclaredMethod("toString", e.getClass());
System.out.println(method.invoke(null, e));
这将根据toString()
参数的类调用e
方法。
答案 3 :(得分:0)
您可以在代码中获取该类的名称并将其返回。
static <E> void out(E e){
System.out.println(toString(e));
}
static String toString(Object o){
return o.getClass().getName();
}
public static void main(String[] args) {
out("");
out(1);
}
答案 4 :(得分:-1)
public class Test
{
static void out(Handler<?> h)
{
System.out.println(h.ref.getClass());
}
private static final class Handler<T>
{
final T ref;
Handler(T ref)
{
this.ref = ref;
}
}
public static void main(String[] args)
{
out(new Handler<>("1"));
out(new Handler<>(new Integer(1)));
out(new Handler<>(new Double(1)));
out(new Handler<>(new ArrayList<HashMap<String, Socket>>()));
}
}
结果
class java.lang.String
class java.lang.Integer
class java.lang.Double
class java.util.ArrayList