In a traditional procedural model, like a parallel arrays model that many newbies use in an inventory program, each element has complete access to the other elements. This isn't a good design because it allows for the easy corruption of data, as well as a lack of flexibility in working with the data that comes from organization.
So let's go ahead and talk about these individual components to a good, encapsulated design.
-Information Hiding, in terms of variables, comes down to restricting access as much as possible. Usually, you will want to make your attributes private, and grant access through access and mutator methods as necessary. This extra control helps prevent any unexpected value changes, as you can validate in the mutator method; and when you get to threading, it helps with providing synchronized access to an attribute via a mutator method.
As it pertains to methods, information hiding basically means that programmers do not need to know how the methods they invoke produce the results, only the results to expect. This saves many headaches down the road, as we are working with modules/section of code.
To put things simply, you don't need to know how Math.pow() evaluates the exponential expression below, only that the result is correct.
double y = Math.pow(3.559, 3);
I really hit hard on this in my tutorial on Moving Away From Parallel Arrays in Java. Basically, with Parallel Arrays, you have attributes associated by corresponding indices in different arrays. With a class, you have a module with a group of sub-modules (methods) as well as features/attributes (instance variables/data). You can use instances of a class to model certain Objects. As it pertains to encapsulation, you do not need to know how the class models the Object, only that it does. You need to know what attributes are stored, and how its methods (or sub-modules) can help you in your programs. In addition, as you move the positions of these Objects in Collections or Arrays, the variables are not messed up like in parallel arrays.
So to put things into context, we have two classes- ArrayList and Collections. With the ArrayList, we don't need to know how stores elements internally, only that it stores them as specified by the method used to insert them. In addition, we don't need to know how the add() method places the elements at the end of the list, only that it does so. When looking at the Collections.sort() method sorts the list, only that it does so successfully. All of these represent encapsulation.
ArrayList<Integer> list = new ArrayList<Integer>(); list.add(5); list.add(3); list.add(10); Collections.sort(list);