The term "Framework" is somehow overburdened with individual and company-specific meanings. When you hear this word, it could designate ....
java.lang.Object
Little bit of truth in all of them?
Wikipedia states that it is ....
A Framework must be something big and complex. That's the impression you get from literature. I believe that "Framework" expresses the undefined hopes and visions of software thinkers, similar to "Component". There is no precise and generally accepted definition of this term. I stick to the old Catalysis way to understand it. But they talk on UML level, and I want to give the view of a Java developer. For me, framework means Reusability by Abstraction.
"Swapping" abstracts the interchange of two elements in an ordered container. Widely used in books about software to explain generic types. Swapping is needed for example in sort-algorithms. Its responsibility:
final Integer[] array = ....;
final int index1 = ....;
final int index2 = ....;
final Integer element1 = array[index1];
array[index1] = array[index2];
array[index2] = element1;
The problem is that you want to implement the swapping of two elements generically once-and-only-once, and you want it strongly typed. But there is a small problem in the few lines of code to do that.
So you either need to hard-code swapping for every thinkable element-type that may need such, or you have a language mechanism that allows generic types. Generic types were introduced in Java 1.5. They make it possible to use an arbitrary (generic) type T
instead of a specific type Integer
. In older Java-versions you could have done this using the "generic" Java super-class java.lang.Object
, but this would not have been type-safe. When using Java generics, the compiler checks the type of the elements that should be in the container, and all related code working on them.
In the following, I use Java generics to implement a type-safe and though generic swap.
public class Swap<T>
{
public void swap(T [] array, int index1, int index2) {
final T element1 = array[index1];
array[index1] = array[index2];
array[index2] = element1;
}
}
Here is some test-code to try this out.
public class Demo
{
public static void main(String[] args) {
final Integer[] integerArray = new Integer[] { 0, 1, };
System.out.println("Before array swap: "+Arrays.asList(integerArray));
new Swap<Integer>().swap(integerArray, 0, 1);
System.out.println("After array swap: "+Arrays.asList(integerArray));
}
}
Output is:
Before array swap: [0, 1]
After array swap: [1, 0]
You might ask now "Where is reusability and abstraction?". Abstraction was done by the Java generics. In case of reusability, you're right. I can not reuse these three lines of code for e.g. List
. Nevertheless I can write another Swap
that cares about java.util.List
. It makes no sense to extend Swap
, because there is nothing reusable in it.
import java.util.List;
public class SwapInList<T>
{
public void swap(List<T> list, int index1, int index2) {
final T element1 = list.get(index1);
list.set(index1, list.get(index2));
list.set(index2, element1);
}
}
Test-code:
final List<String> stringList = new ArrayList<>();
stringList.add("A");
stringList.add("B");
stringList.add("C");
stringList.add("D");
stringList.add("E");
System.out.println("Before list swap: "+stringList);
new SwapInList<String>().swap(stringList, 1, 3);
System.out.println("After list swap: "+stringList);
Outputs:
Before list swap: [A, B, C, D, E]
After list swap: [A, D, C, B, E]
Unfortunately there is no Java interface that makes array and list interchangeable. I must access the array by indexing, and the list by calling get()
and set()
.
There is another ordered Java container that may need swapping. Other than List
, a Set
contains no duplicates, and has no order. LinkedHashSet
is different, it keeps the order in which elements were added.
Working with Set
means you have no get()
and set()
. Again we need another implementation for swapping elements.
1 | import java.util.LinkedHashSet; |
Oops, these are definitely more than three lines. Unfortunately the nature of Java Set
makes it impossible to access specific indexes. That is the reason why we need two loops: first loop retrieves the elements to be swapped, second loop (over a clone) establishes the new order after having cleared the set completely.
final Set<Float> floatList = new LinkedHashSet<>();
floatList.add(1.0f);
floatList.add(100.0f);
floatList.add(10000.0f);
System.out.println("Before linkedSet swap: "+floatList);
new SwapInLinkedSet<Float>().swap(floatList, 1, 2);
System.out.println("After linkedSet swap: "+floatList);
This test code outputs:
Before linkedSet swap: [1.0, 100.0, 10000.0]
After linkedSet swap: [1.0, 10000.0, 100.0]
These swaps maybe were examples for the abstraction that Java generics provide, but not for implementation abstraction, and definitely not for reusability. We had to use three different implementations for three different Java container types. Can we do better? You guessed right, I will try this in my next Blog article about frameworks as seen by Java.
ɔ⃝ Fritz Ritzberger, 2016-11-20