Java 通过泛型方法执行重载
我的动机是创建一组名为toString()的重载函数,它接受任何对象(或者至少是我感兴趣的对象),并创建一个用于调试的字符串。然后我还希望有一个out()方法,而不必重新创建相同的(繁琐的)重载 我发现这段代码得到的结果是toString(e)in out()总是调用toString(Object)。在研究了泛型之后,我找不到解决这个问题的方法。因此,如果有人能洞察如何做到这一点,我将不胜感激 总而言之:Java 通过泛型方法执行重载,java,generics,Java,Generics,我的动机是创建一组名为toString()的重载函数,它接受任何对象(或者至少是我感兴趣的对象),并创建一个用于调试的字符串。然后我还希望有一个out()方法,而不必重新创建相同的(繁琐的)重载 我发现这段代码得到的结果是toString(e)in out()总是调用toString(Object)。在研究了泛型之后,我找不到解决这个问题的方法。因此,如果有人能洞察如何做到这一点,我将不胜感激 总而言之: 是否有一种优雅的方法来实现out()方法,利用toString()的现有重载 这可以用泛
- 是否有一种优雅的方法来实现out()方法,利用toString()的现有重载李>
- 这可以用泛型实现吗
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); } }
公共级A3{ 静态空隙率(E){ System.out.println(toString(e)); } 静态字符串到字符串(对象o){ 返回“对象”; } 静态字符串到字符串(字符串str){ 返回“字符串”; } 静态字符串到字符串(整数i){ 返回“整数”; } 静态字符串到字符串(SomeObject o){ 返回“对象的描述”; } 公共静态void main(字符串[]args){ 出(“”); 输出(1); } }
编辑:用于阐明含义的扩展示例。调用哪个方法是在编译时确定的。如果需要动态检查,必须自己编写代码 唯一的方法是使用字符串
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);
}
注意:除非执行此操作,
toString((Object)“hello”)
将返回“Object”您可以在代码中获取类的名称并返回它
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);
}
静态作废(E){
System.out.println(toString(e));
}
静态字符串到字符串(对象o){
返回o.getClass().getName();
}
公共静态void main(字符串[]args){
出(“”);
输出(1);
}
您必须使用反射来实现这一点(如果您可以使用反射)
这将基于
e
参数类调用toString()
方法。可能有多种方法来实现您实际想要实现的目标。根据您提到的代码和约束条件,可能有各种方法来实现您想要实现的目标。但关注这一点:
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>>()));
}
}
是否有一种优雅的方法来实现out()方法,利用toString()的现有重载
为了利用这些方法,您必须分派到所需的方法。该方法必须在编译时已知,或者在运行时根据给定对象的类型确定。但是,这不能基于泛型和内部语言来完成,因为在编译过程中泛型参数基本上被Object
替换
解决此问题的一种方法是在公共映射中为所需的toString
方法注册Function
s,并在运行时查找这些函数
请注意,对于您实际想要做的事情,这不一定是一个“好”的解决方案,但它以一种通用且易于扩展的方式展示了一种“利用现有重载”的方法
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);
}
}
import java.util.LinkedHashMap;
导入java.util.Map;
导入java.util.function.function;
公共类泛型排序
{
私有静态最终映射为什么不在对象中重写Object#toString
,然后去掉这个Rube Goldberg东西?这个Rube Goldberg东西是用来创建一个toString()的,只用于mig目的:-)我可能无法更改要格式化的类。还有toString()大多数内置对象都不能提供方便的信息。明白了。尽管你可以扩展或匿名化不能直接修改的类,并添加格式化功能(如果它们不是最终的,也就是说)。看看你的设计,你正在进入一个痛苦的世界-公平警告:)@mene我同意痛苦的世界:-)“双重分派”问题:)或getSimpleName()
而不是getName()
;我提供的第一个示例是正确的。我扩展了示例以激发我寻求更复杂解决方案的原因。甚至比测试和避免编码测试更好(因为我认为列表可能会增加)toString
:toString(Object o){return o==null?”:o.getClass().getSimpleName();}
@Peter我明白你的意思。但是创建out()的重载似乎也遇到了同样的麻烦。你建议的toString
是最好的解决方案(在不使用重载时)我更喜欢它。out
方法应该是直接的。我希望看到的是一个解决方案,out
可以在不接触toString
方法的情况下实现。@Wisoft可以,但toString有缺陷,因为类型没有动态检查(参见我的最后一行)这一点你是对的。这可能会造成混乱,如果我不知道确切的类型,重载的toString
可能会给出一个误导性的答案。这是执行toString
建议并避免静态重载的很好的理由。这应该实现什么?也许我误解了你的意图o do,但这将显示进入方法“out”的对象的类型“,不管这个对象是什么。我不是OP。我认为他选择的字符串仅仅是示例,而不是他真正想要做的,他只是想要一个基于类型的字符串,但不一定是类型的名称。这是一个泛型问题,不仅仅是打印object.getClass
。如果e.getClass()
是签名中某一类型的子类型?这很有可能。它似乎正是我想要的工作方式。子类型问题:如果类中不存在确切的签名,则调用getDeclaredMethod
将引发异常。即使存在一个方法,它也会采用父类型。这对我很有效p
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
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);
}
}