Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 通过泛型方法执行重载_Java_Generics - Fatal编程技术网

Java 通过泛型方法执行重载

Java 通过泛型方法执行重载,java,generics,Java,Generics,我的动机是创建一组名为toString()的重载函数,它接受任何对象(或者至少是我感兴趣的对象),并创建一个用于调试的字符串。然后我还希望有一个out()方法,而不必重新创建相同的(繁琐的)重载 我发现这段代码得到的结果是toString(e)in out()总是调用toString(Object)。在研究了泛型之后,我找不到解决这个问题的方法。因此,如果有人能洞察如何做到这一点,我将不胜感激 总而言之: 是否有一种优雅的方法来实现out()方法,利用toString()的现有重载 这可以用泛

我的动机是创建一组名为toString()的重载函数,它接受任何对象(或者至少是我感兴趣的对象),并创建一个用于调试的字符串。然后我还希望有一个out()方法,而不必重新创建相同的(繁琐的)重载

我发现这段代码得到的结果是toString(e)in out()总是调用toString(Object)。在研究了泛型之后,我找不到解决这个问题的方法。因此,如果有人能洞察如何做到这一点,我将不胜感激

总而言之:

  • 是否有一种优雅的方法来实现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);
    }

}