【问题标题】:How can I make a Java function that accepts any type of variable?如何制作一个接受任何类型变量的 Java 函数?
【发布时间】:2018-10-24 16:07:56
【问题描述】:

我想创建一个可以接受任何传入变量的函数,无论类型如何(intdoubleString 或其他对象),然后可能确定变量的类型并有条件地对输入。

我该怎么做?

【问题讨论】:

  • 看看instanceof,把你的论点变成一个对象。或者,看看泛型(尽管如果你只是在玩这种语言,它们会受到更多限制)。
  • 如果您接受“对象”,它将接受大多数类型,但对于原语,您需要“重载”该方法以接受每种类型。
  • 你认为你为什么需要这个?
  • 您可能想研究钻石方法、泛型和多态性。在 java 中,通常您不会按类型进行模式匹配。很可能你想做的事情可以通过多态来实现。

标签: java function object types


【解决方案1】:

你没有。你想要做的是重载你的函数并相应地实现每个案例。这就是类型语言的美妙之处和面向对象编程的美妙之处。

【讨论】:

  • 在很多情况下,不可能知道所有可能进入的类型,但仍然可以定义如何处理某些类型的规则。想想例如任何序列化程序,例如 JSON 序列化程序(由 OP 授予的情况可能更微不足道)
  • @OlegSklyar 正是如此。正如 OP 所说,他是一个新手,我强烈怀疑这个问题源于无类型语言体验。如答案所示,试图规避 Java 的类型方面将不可避免地变得复杂。因此,我建议支持重载。使用功能丰富的语言来有效地规避这些功能是没有意义的。我会说要么考虑案例和超载,要么语言不适合这个问题。
【解决方案2】:

根据您是否想将装箱值与原子值区分开来,您有以下选项,所有这些都在下面的测试中进行了演示:

  1. 使用Object:您将失去原子类型,因为它们将被装箱
  2. 使用泛型:您将失去原子类型,因为它们将被装箱
  3. 对所有原子类型使用上述任何一种方法以及重载

    Class<?> anyObject(Object val) {
        return val != null ? val.getClass() : null;
    }
    
    <T> Class<?> anyGeneric(T val) {
        return val != null ? val.getClass() : null;
    }
    
    @Test
    public void anyAsObject_alsoViaGenerics() {
        assertEquals(String.class, anyObject("a string"));
        assertEquals(String.class, anyGeneric("a string"));
        // atomic arrays are Ok
        assertEquals(boolean[].class, anyGeneric(new boolean[]{}));
        assertEquals(int[].class, anyGeneric(new int[]{}));
        // atomic: auto-boxed and thus not Ok
        assertEquals(Boolean.class, anyObject(true));
        assertEquals(Boolean.class, anyGeneric(true));
        assertEquals(Integer.class, anyObject(125));
        assertEquals(Integer.class, anyGeneric(125));
    }
    
    // with overloading
    
    Class<?> any(Object val) {
        return val != null ? val.getClass() : null;
    }
    
    Class<?> any(boolean val) {
        return boolean.class;
    }
    
    Class<?> any(int val) {
        return int.class;
    }
    
    @Test
    public void any_overloadedForAtomic() {
        assertEquals(String.class, any("a string"));
        assertEquals(Boolean.class, any(Boolean.TRUE));
        assertEquals(Integer.class, any(Integer.valueOf(125)));
        assertEquals(boolean[].class, any(new boolean[]{}));
        assertEquals(int[].class, any(new int[]{}));
        // atomic
        assertEquals(boolean.class, any(true));
        assertEquals(int.class, any(125));
    }
    

【讨论】:

  • 对于您的通用方法,可能以下签名更好:&lt;T&gt; Class&lt;? extends T&gt; anyGeneric(T val)
【解决方案3】:

最好和最简单的方法是使用重载技术... 多次写你的方法,每次都有不同的签名...... 看看这个:

public void myFunc(int i)
{
System.out.println(i);
}
public void myFunc(double d)
{
System.out.println(d);
}
public void myFunc(String s)
{
System.out.println(s);
}
public void myFunc(boolean b)
{
System.out.println(b);
}

【讨论】:

    【解决方案4】:

    重载是最推荐的选项,大多数时候您不需要接受任何类型变量的函数。

    但是接受任何Object 的函数呢?您可能需要使用instanceof 并根据数据类型处理它们。

    instanceof的用法:[Name of object instance] instanceof [Name of object type to match]

    instanceof 返回 boolean: true 当且仅当对象实例的类型与要匹配的类型匹配。

    接受“任何变量类型”的函数或方法的一个示例:

    public static void method(Object obj) {
        if (obj instanceof String)
            System.out.println("I am a String!");
    
        if (obj instanceof Integer)
            System.out.println("I am an Integer!");
    
        // Similarly for other types of Object
        if (obj instanceof ... )
            ...
    
        // The .getClass() is for any Object
        System.out.println(obj.getClass());
    }
    

    请注意,不建议制作接受任何类型变量的函数。

    【讨论】:

    • 只是一个补充@genisome:请使用重载而不是instanceof,因为编译器将能够在编译时验证您的方法调用。当您使用instanceof 时,无法在编译时进行任何检查,您需要依靠自己的编码技能来避免运行时错误。
    • 我加粗了重载部分,说明重载在几乎所有情况下都是可取的。函数通过任何类型的对象是非常罕见的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多