6

I would like to make a function that can accept any incoming variable, regardless of type (int, double, String or other objects), and then possibly determine the type of variable and act conditionally on the type.

How can I do this?

genisome
  • 47
  • 1
  • 1
  • 7
  • 1
    Take a look at `instanceof`, and make your argument an object. Alternatively, look at generics (although they're a bit more restrictive if you're just playing around with the language). – hnefatl May 14 '18 at 22:19
  • 1
    possible duplicate of https://stackoverflow.com/questions/7815528/what-are-generics-in-java – Hubert Bratek May 14 '18 at 22:19
  • If you accept "Object" it will accept most types, but for the primitives, you would need to "overload" the method to accept each type. – JustinKSU May 14 '18 at 22:22
  • 3
    Why do you think you need this? – shmosel May 14 '18 at 22:22
  • You might want to research diamond methods, generics and polymorphism. In java generally you do not do pattern matching by type. Most likely what you want to do can be achieved with polymorphism. – Miko May 14 '18 at 22:29
  • Sounds like [the XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What are you actually trying to do with this? – Andy Turner May 14 '18 at 22:34
  • In which case will you devise a method where one variable is of "any type or Object"? – Ṃųỻịgǻňạcểơửṩ May 14 '18 at 23:20

4 Answers4

4

Overloading is the most recommended option, most of the time you do not need a function that accepts any type of variable.

But what about a function that accepts any Object? You may need to use instanceof and handle them depending of the data type.

Usage of instanceof: [Name of object instance] instanceof [Name of object type to match]

instanceof returns a boolean: true if and only if type of object instance matches the type to match.

One example of a function or method that accepts "any variable type:"

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());
}

Please note that making a function that accepts any type of variable is not recommended.

  • 1
    Just an addition @genisome: Please use overloading in preference of `instanceof` as the compiler will be able to verify your method calls at compile time. When you use `instanceof`, no checks can be made at compile time and you will need to rely on your coding skills to avoid runtime errors. – vatbub May 14 '18 at 23:54
  • I bolded the Overloading part stating that Overloading is preferable in almost all circumstances. A function passing through an object of any type is very rare. – Ṃųỻịgǻňạcểơửṩ May 15 '18 at 00:44
2

Depending if you want to distinguish boxed values from atomic or not you have the following options, all of which are demoed in the test below:

  1. use Object: you will loose atomic types as they will be boxed
  2. use generics: you will loose atomic types as they will be boxed
  3. use either of the above along with overloading for all atomic types

    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));
    }
    
Oleg Sklyar
  • 9,834
  • 6
  • 39
  • 62
  • For your generic method, probably following signature is better: ` Class extends T> anyGeneric(T val)` – YoYo May 14 '18 at 23:41
0

You don't. What you want to do is overload your function and implement each case accordingly. This is the beauty of typed languages and the beauty of object oriented programming.

Samuel
  • 2,106
  • 1
  • 17
  • 27
  • 1
    There are tons of cases where it is impossible to know all types that might go in, but one can still define rules how to deal with some types. Think e.g. of any serializer, such as JSON serializer (granted the case by OP is probably much more trivial) – Oleg Sklyar May 14 '18 at 22:46
  • @OlegSklyar Precisely. As stated by OP, he's a newb, and I strongly suspect this question originating from an untyped language experience. As shown in the answers, it would be inevitably complicated to try to circumvent the typing aspect of Java. Hence my advice to favor overloading. There's no point in using a feature-rich language to effectively circumvent these features. I would say either consider the cases and overload or maybe the language is not suited for the problem. – Samuel May 15 '18 at 07:32
0

The best and easiest way is using overload Technique... write your method several times, each time with different signatures... look at this:

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);
}
Majva
  • 88
  • 1
  • 5