0

I have recently run into the following error which really confuses me. I have imported reflect. I have a class (called worker) with a field which is a private int called numOfJobs. In the constructor of Worker, numOfJobs is set to 0. Then, in a tester class, I create an instance of type worker:

    waterBenders[0] = new Worker();
    Field []fields = waterBenders[0].getClass().getDeclaredFields();
    Field privateFieldJobs = fields[0];
    privateFieldJobs.setAccessible(true);

    try{

          System.out.println(privateFieldJobs.get(waterBenders[0]));

          System.out.println(privateFieldJobs.get(waterBenders[0]).getClass());

          System.out.println((int)privateFieldJobs.get(waterBenders[0]));
    }

It is the third line in the try box which is contains the error. The first two lines print:

    0    
    class java.lang.Integer

This makes sense to me. However, if the object privateFieldJobs.get(waterBenders[0]) is an object of type Integer with "value" 0, then why should (int)privateFieldJobs.get(waterBenders[0]) throw the error:

    Cannot cast from java.lang.Object to int

If I was to create a normal object of type Integer, then this type of casting usually works. What is so special about this example? I imagine it has something to do with the fact that this Integer object is coming from the fields array.

My worker class is essentially:

    public class Worker extends Unit{
      private int numOfJobs;

      public Worker(Tile position, double hp, String faction) {
        super(position, hp, 2, faction);   
        this.numOfJobs = 0;
      }

      public int getNumOfJobs(){
        return this.numOfJobs;
      }
    }

Any help would be appreciated.

1
  • 1
    Could you edit your question to include the definition of the Worker class? Commented Oct 2, 2019 at 19:59

2 Answers 2

3

It is because Field#get returns an Object, and you can not cast any Object type to a primitive type in java. If you want the primitive integer value from an Integer object, you can do something like this

Integer field = (Integer) privateFieldJobs.get(waterBenders[0]);
int value = field.intValue();
Sign up to request clarification or add additional context in comments.

4 Comments

You can simply do int field = (Integer) privateFieldJobs.get(waterBenders[0]);.
No you would need to do int field = ((Integer) privateFieldJobs.get(waterBenders[0])).intValue();
Yes, I just did it like that so it was simpler to read for him
@KyleAure you don’t need to call intValue() manually when assigning an Integer to an int, since Java 5, that is since fifteen years now.
3

Basically you are attempting this:

Integer i=1;
Object o=i;
int val=(int)o;

It has no reason to work, that is why it does not.

Either cast it back to Integer (as you see, it is not necessary for a println, as the correct toString() gets invoked anyway, but it is required for unboxing), or you can try using getInt():

int val1=(Integer)privateFieldJobs.get(waterBenders[0]);
int val2=privateFieldJobs.getInt(waterBenders[0]);


Well, I was wrong about the latter: while both of them work for an int, but getInt() does not work on an Integer:

import java.lang.reflect.*;

class Ideone {
    public Integer objInt=23;
    public int valInt=42;

    public static void main (String[] args) throws java.lang.Exception {
        Field objField=Ideone.class.getField("objInt");
        Field valField=Ideone.class.getField("valInt");

        Ideone test=new Ideone();

        System.out.print("objInt-get: ");
        System.out.println(objField.get(test));

        System.out.print("objInt-getInt: ");
        try{
            System.out.println(objField.getInt(test));
        } catch (Exception ex) {
            System.out.println(ex.getClass());
        }

        System.out.print("valInt-get: ");
        System.out.println(valField.get(test));

        System.out.print("valInt-getInt: ");
        System.out.println(valField.getInt(test));
    }
}

(class is called Ideone, because it can be tried there: https://ideone.com/91xzmc)
Output:

objInt-get: 23
objInt-getInt: class java.lang.IllegalArgumentException
valInt-get: 42
valInt-getInt: 42

So one can use both get() and getInt() on an int field, but when the field is Integer, only get works. (The ex.getClass() magic is just about shortening the message, by default there is a long explanation which does not fit in a line).

Side note: usage of number classes, like Integer, means creating objects, on the heap (which can add to heap fragmentation, and can make extra work for the garbage collector). If you do not specifically need a number to be null-able, or to be an object for any other reason (some exotic serializers may need that), use int. It is faster, lighter and even shorter to type, plus needs no touch of Shift (for I).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.