The short and simple answer is that arrays are for fixed-length lists, and ArrayList objects are for variable-length collections. Both allow efficient access to elements by position (index), using someArray[index] for arrays, or someArrayList.at(index) for ArrayList objects.
An array is a fixed number of elements, stored sequentially so that elements can be quickly accessed by an index. Once created, the length of an array can never change. The elements of an array must all be of the same type, and that type can be either a primitive type (int, double, char, etc.) or an object type (class, interface, enum, or another array).
ArrayList is a class type (available in generic and "plain" versions). Either way, an ArrayList is an object that models a variable length array. New elements can be added or inserted, and existing elements can be deleted, changing the length of the array, with remaining elements shifted as needed so that the index values are always sequential and start with 0.
Array lists can only store object types, but each of the primitive types have a corresponding "wrapper" class, and the compiler provides automatic "boxing" conversions to convert primitive values to an objects when needed, and "unboxing" conversions to go the other way.
A plain ArrayList can store elements of (almost) any object type. A generic ArrayList
can store only object of type SomeType or of a type that (directly or indirectly) extends SomeType. A generic ArrayList accepts objects of any type that implements the SomeInterface interface. The "almost" is that you can't use array types, even though they are objects, because they don't have class names. (There's an internal class name beginning with a '[' character, but that's not a Java identifier that you can use in a generic type.)