A graphical-component library can provide
protected void paintComponent(Graphics g) as a subclass customization hook, as in javax.swing.JComponent. A subclass overrides it to draw its own contents while the library retains responsibility for the surrounding painting protocol. A protected method in Java is accessible to code in the declaring package and to subclasses in other packages subject to the receiver restriction; it is not simply a public method and not exclusively subclass-visible.The benefit is controlled extensibility without exposing an ordinary client operation. If the method were private, external subclasses could not override and reuse it as the intended hook. If it were public, arbitrary clients could call it outside the normal painting lifecycle and the library would have a wider public contract to maintain. Protected hooks still require documented invariants because subclass code participates in the implementation.
An immutable library value such as
java.lang.String can be a final class in Java. No class can extend it, so a client receiving a String cannot secretly receive a subclass that changes the behavior of its methods. This protects assumptions about value semantics in code using strings as keys or trusted identifiers.The benefit is a closed implementation contract. Without
final, subclasses might override methods inconsistently or introduce behavior incompatible with the library's intended guarantees. Making a class final does not by itself make its fields immutable; a correct immutable implementation also controls its state. The cost is that clients cannot customize it by inheritance and must instead use composition or a different abstraction.A collections library can supply a genuinely generic method in Java whose own type parameter connects the input element and the result element type:For example,
java
static <T> java.util.List<T> oneElement(T item) {
java.util.List<T> result = new java.util.ArrayList<T>();
result.add(item);
return result;
}List<String> xs = oneElement("sample"); is type-checked without a cast. The method can also construct a List<Integer> from an integer object. The standard library's Collections.singletonList is another example of this type relationship, though its returned list is unmodifiable.The benefit is one reusable implementation with compile-time argument/result consistency. A raw
List result would lose element-type information, invite unchecked calls and require casts that may fail later. Separate methods for every element type would duplicate code. Merely enclosing a concrete type in angle brackets, such as returning List<String>, does not make a method generic; the method here declares <T>. Type erasure means the guarantee is primarily a source-level type check, not a distinct runtime class for each type argument.A growable-array library should store its backing Java array and logical size in private fields in Java. Public methods such as
add, get and remove can enforce bounds and keep the size consistent with the stored elements. The representation can later change without requiring clients to modify direct field accesses.The benefit is preserving invariants through encapsulation. If clients could assign the size or replace the backing Java array directly, they could create negative sizes, report elements that do not exist, or modify entries without the library's checks. Accessor methods should not expose a mutable backing object indiscriminately, since a private field alone does not prevent that indirect route. Private fields also do not provide a general security boundary against privileged reflection or native code; the point here is ordinary library access discipline.
A collections library can specify a
List<E> Java interface, with different implementations such as ArrayList<E> and LinkedList<E>. A method accepting List<E> can iterate or access elements according to the documented list contract without requiring one particular storage representation. Each implementation may also extend its own appropriate class superclass.The benefit is separating a usable contract from its implementation. A parameter restricted to a concrete
ArrayList<E> would exclude a linked list implementation and unnecessarily expose the storage choice. Requiring all providers to extend one concrete class would couple them to its implementation and consume Java's single class-inheritance relationship. Interfaces permit multiple implemented contracts, though clients must rely on the stated contract rather than assuming every optional operation is supported or has the same time complexity. Articles by others on the same topic
There are currently no matching articles.