Here, the actual method being used is Integer.equals(Object). Since 343 is an int, it is first boxed into an Integer, and then reference widening takes place from Integer to Object. Integer overrides equals(Object) so that an Integer reference will be equal to an Object reference only if the Object reference actually points to an Integer object, and if both Integer objects contain the same value (which in this case is true.) The reason why there is not a == test on the references themselves is because Integer overrides Object.equals(Object).
Strings also override Object.equals(Object), but arrays do not (although you can use the Arrays.equals() and Arrays.deepEquals() static methods of the java.util.Arrays class.)
All code in my posts, unless a source is explicitly mentioned, is my own.
x is of type Integer, and 343 is initially an int. It gets boxed into an Integer, and then the comparison takes place. All wrappers override Objects.equals and Object.toString. So, they are compared correctly.
String overrides Object.equals, so the two are compared correctly.
There is something called a String pool. When JVM recognizes a String literal it's placed into this pool. And, if the same literal appears again in the code its reference points the pre-existing string, making this condition true. This is Java's scape route for String immutability. If the pool didn't exist we'd have more out of memory errors.
I am not ultra sure about this one, but I think Object.equals is used here, because Java treats all arrays as objects. We know Object.equals compares references, so its false.
And, of course the two arrays are distinct objects with distinct addresses. False.