Protected access can be tricky. You can only access protected members from within the context of the inherited class. For instance, you can access B's 'i' variable (inherited from A), but not A's through an A reference, since B is in a separate package.
From the JLS:
�6.6.2 Details on protected Access A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.
Try experimenting with this. Write some practice code. Test it out.
The setI() method is not responsible for the implementation of the Super type. It operates on an outside super reference. Because Sub is not in the same package (and because setI() has nothing to do with the implementation of Super), it cannot modify the protected members of Super.
Look at it this way. The protected member variable i is functions just like a public variable while you are in the same package. You can access it anywhere, anytime.
But once you move it outside the package, that's where the protected part kicks in. It functions like a private variable in every instance except when it is being accessed via inheritance (ie, if the sub-class is an implementation of the parent with the protected variable).
This is because Child is in the same package as Parent, and therefore has free access to Parent's x variable, as though it were public.
But if you move Parent to its own package:
Now you will get an compiler error on "System.out.println(p.x)" that says "The field Parent.x is not visible" just as though it were a private variable. However the second println statement functions fine because Parent.x is being accessed via the child class. This is what distinguishes x from being a private variable.