values can be stored in an object only if you have called a field in the class or method.
This statement doesn't make any sense. I can't tell if it is wrong or right, it just... doesn't make sense.
it shouldn't be able to call its value field without instantiating an object since value isn't static. I just can't wrap my head around how this is even possible.
Javac sees that and goes: Hey, you're shoving a square peg (a constant of type int) into a round hole (an object typed variable) - this doesn't make sense. Except, explicitly called out in the Java Language Specification, if an int expression shows up in a place where int expressions should not be, but an Integer expression works fine, then 'apply autoboxing'.
'apply autoboxing' means: Assume the programmer meant to write: Integer.valueOf(the expression) instead of what they wrote.
Thus:
Integer x = 56;
Integer x = Integer.valueOf(56);
are identical. They are so identical, they produce the same bytecode. That call to valueOf is in your class file, no matter how you write it. Let's test:
> cat Test.java
class Test {
    Integer x = 56;
}
> javac Test.java
 (`javap` is part of java distributions and prints bytecode)
> javap -private -c Test
Compiled from "Test.java"
class Test {
  java.lang.Integer x;
  Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: bipush        56
       7: invokestatic  #7                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      10: putfield      #13                 // Field x:Ljava/lang/Integer;
      13: return
}
Look at that - calls to the static method Integer.valueOf, even though Integer.valueOf appears exactly nowhere in our Test.java file.
So, how does Integer.valueOf work?
Essentially, it works like this:
package java.lang;
public class Integer {
    private static final Integer[] CACHE = generateCache();
    private final int value;
    public Integer(int value) {
        this.value = value;
    }
    private static Integer[] generateCache() {
        for (int i = 0; i < 256; i++) {
            CACHE[i - 128] = new Integer(i);
         }
    }
    public static Integer valueOf(int v) {
        if (v >= -128 && v < 128) return CACHE[i + 128];
        return new Integer(v);
    }
}
In other words, the Integer class pre-creates 256 integer objects, from -128 to +127 (why those values? Eh, cuz sun thought those would come up so often, it'd be worthwhile to cache them, 25 years ago). If you valueOf() with a value between -128 and +127 you get one of the caches. If you valueOf outside of it, you get a new object.
We can prove that too:
> cat Example.java
class Example {
    public static void main(String[] args) {
        Integer a = -100;
        Integer b = -100;
        Integer c = 200;
        Integer d = 200;
        System.out.println("a == b? " + (a == b));
        System.out.println("c == d? " + (c == d));
        System.out.println("ident-hash a: " + System.identityHashCode(a));
        System.out.println("ident-hash b: " + System.identityHashCode(b));
        System.out.println("ident-hash c: " + System.identityHashCode(c));
        System.out.println("ident-hash d: " + System.identityHashCode(d));
    }
}
> java Example.java
a == b? true
c == d? false
ident-hash a: 1880794513
ident-hash b: 1880794513
ident-hash c: 1991313236
ident-hash d: 736778932
This code shows that for -100, that Integer.valueOf call is returning the exact same object (== compares reference identity, i.e.: Is it the same object, when used on objects, it does not compare values. a and b are just pointing to the same object, whereas c and d are pointing at different objects that have the same values).
It's like a bunch of identical houses build in the suburbs someplace: a and b are like pieces of paper with the same address written on them, whereas c and d are like pieces of paper with a different address on each, but the two houses at these addresses look the same.