3

In Java, consider the following piece of code:

int myPrimitiveInt = 5;
Integer myObjectInt = 4;

Object fromPrimitive = myPrimitiveInt;
Object fromObject = myObjectInt;

System.out.println(fromPrimitive.getClass());
System.out.println(fromObject.getClass());
System.out.println(int.class);

And the output:

class java.lang.Integer
class java.lang.Integer
int

What I would like, is a way to also get the output int for the first println.


WHY?, you will ask. Well, for one thing, I would just like to know if something like this is even possible.

But the actual practical reason behind this is an abstraction layer for testing private methods with primitive type arguments via reflection. The minimal code:

package testing;

import java.lang.reflect.Method;

public class Testing {
    private static void doStuff(int a) {
        System.out.println("primitive: " + ((Object) a).getClass());
    }

    public static void main(String[] args) throws ReflectiveOperationException {
        Reflect.reflect(Testing.class, "doStuff", 10);
    }
}

abstract class Reflect {
    static Object reflect(Class<?> clazz, String methodName, Object arg) throws ReflectiveOperationException {
        Method method = clazz.getDeclaredMethod(methodName, arg.getClass());
        method.setAccessible(true);
        return method.invoke(null, arg);
    }
}

The output:

Exception in thread "main" java.lang.NoSuchMethodException: testing.Testing.doStuff(java.lang.Integer)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at testing.Reflect.reflect(Testing.java:17)
at testing.Testing.main(Testing.java:11)

Expected output:

primitive: class java.lang.Integer

Or even better (if possible at all):

primitive: int

Note: I know I can do clazz.getDeclaredMethod(methodName, int.class). The whole point of this post is to make this procedure more abstract. Please do not give me answers suggesting to pass the argument types to the reflect method!

Snackoverflow
  • 5,332
  • 7
  • 39
  • 69
  • 1
    primitive types cannot be cast to Object. They will always be boxed and then you cannot tell what the origin was. For `Integer` the first origin is always a primitive type – jontro Oct 14 '17 at 18:12
  • Not possible. Both the 5 and the 4 go through the same autoboxing process in your example; one just gets autoboxed later. – user2357112 Oct 14 '17 at 18:12
  • No, you can't. You force the primitive into an object, so it's boxed. That creates an instance of ``Integer``. – f1sh Oct 14 '17 at 18:13
  • Study: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html – PM 77-1 Oct 14 '17 at 18:13
  • 1
    Possible duplicate of [Why do we use autoboxing and unboxing in Java?](https://stackoverflow.com/questions/27647407/why-do-we-use-autoboxing-and-unboxing-in-java) – Joe C Oct 14 '17 at 18:13
  • 1
    You can't. Because of that some classes have many overloaded methods which aside from handling Object will also handle primitive types (to avoid boxing). – Pshemo Oct 14 '17 at 18:16
  • So if `int` would be autoboxed into `Integer`, why would executing this code throw a `ReflectiveOperationException` if I would erase the method `doStuff(Integer a)`, so that the only method left takes a primitive argument? TBH, this is the reason I created this post. I cannot reflect any methods with primitive types in this manner. – Snackoverflow Oct 14 '17 at 18:25

2 Answers2

4

What happens when you write Object x = 10

The int is autoboxed, which makes it into an Integer with value 10.

Why can't this be detected afterwards

Because there is no difference between the Integer with value 10 that was autoboxed and another Integer with value 10

How can I get around this

You need to add separate methods to overload for primitive values, these can handle the primitive values, so they do not get autoboxed.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
jrtapsell
  • 6,719
  • 1
  • 26
  • 49
2

A primitive type is never "cast" to an object.

A primitive may be "autoboxed" into an object, but you can never determine this in code, since autoboxing is just code that is added by the compiler and is indistinguishable from the same code that you might have added by hand.

Snackoverflow
  • 5,332
  • 7
  • 39
  • 69
DwB
  • 37,124
  • 11
  • 56
  • 82