Showing posts for tag: java

Don't use Java primitives

July 3rd 2009

Java syntax evolved from C’s and as a result has the primitives:

byte short int long float double boolean char

These primitives can be considered to be the building blocks for all other value objects within Java and allow users to hold data as fields and variables. However, I would argue that they are not useful and a good rule of thumb is to not use them at all. Instead Java provides the classes:

Byte Short Integer Long Float Double Boolean Character

These are classes for fully fledged, immutable, value objects which can be used in much the same way as the basic primitives, but offer the following advantages:

1. They can be used in generics. This is possible:

new ArrayList<Integer>();

But this is not:

new ArrayList<int>();

2. They can still be passed into library functions that demand primitives. Auto boxing means that a method signature with int can still be called with an Integer objects transparently. Likewise, a function returning an int can be assigned to an Integer.

3. They offer all the expected methods for use in debugging and collection handling, such as toString, equals and hashcode.

4. They can be null. While there is a lot of discussion as to whether applications should be passing null around, it is still sensible to ask the question what should be returned from a method such as getIdIfPresent if there is no ID. With primitives, you’d be forced to return a value that represented a nonexistent result, such as -1. WIth real objects, you have the option of returning null.

5. Primitives in java are passed by value, whereas objects in java are passed by reference. This may not have a huge impact on how you would handle Integer vs int, however. This is because the objects that represent the primitive types are immutable, and therefore you cannot change the value of any of the parameters passed. Despite this, I would recommend using objects over primitives, simply because it means you don’t have two kinds of behaviour represented in your code.

tags: java

Consider overriding Equals and Hashcode as a general rule

June 15th 2009

In both C# and Java, objects have methods for checking equality and producing hashcodes. For the purposes of this post I’ll mostly refer to the java methods equals and hashcode, but C# has the equivalent methods Equals and GetHashCode respectively.

If you have two objects, and you wish to test their equality, the equals method is the obvious choice. The default implementation in java is simply to check if the references are the same, i.e. the default implementation of this:

objA.equals(objB)

is the same as this:

objA == objB

However, value objects such as String, have a different implementation of equals:

public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n— != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}


This implementation actually checks the value of another string that is passed to it, and will return true if the type and the value match.

Seeing this implementation, I postulate the following: All objects that represent a value should override equals and by extension hashcode.

You might argue that this is pointless if you aren’t performing comparisons between these objects of this type. What is the point of writing and maintain code that never gets executed at any time within your application? Well, there are a few reasons.

Firstly, utilities such as java’s Collections classes use equals and hashcode to manage their contents and to spot duplicates. Since the default behaviour is assume that different instances are not equal, it is possible, for example, to have multiple instances of the same value object in a hashmap key set. Bugs like this are subtle and can prove difficult to spot. Often they might be missed during unit testing, because it is possible that the scenario where multiple instances with the same value may not have been considered.

Another reason to properly override equals regularly is that it aids testability. If you are using matchers for testing the following line will be a common one in your tests:

assertThat(objA, equalTo(objB));

If you are using the default implementation of equals, then what that line does is check that objA and objB are the same instance. That would mean that the above assertion would be equivalent to the following if you have not overridden equals.

assertThat(objA, same(objB));

This is clearly not the case. The intent expressed by equalTo and same is quite definitely different.

A third reason to implement equals and hashcode on your classes is that if you are producing code to be used by another group of individuals or any sort of API, you have no idea how those individuals intend to use your objects. Even if you aren’t handling them in collections, they quite easily might.

However, as I alluded to earlier, there are reasons not to implement equals and hashcode on classes. The first that this is a lot of code to implement, test and maintain on many classes. Having said this, I would argue implementing them is still the right thing to do. There are a few cases where implementing these methods just really doesn’t make sense. That would be on things like static utility classes which never have objects instantiated. Another example might be on objects where the instance itself can be considered the value, for example a node in a representation of a tree.

tags: java

subscribe subscribe to this tag

Welcome. Here you'll find Adam Scott's blog and photos. Adam is an agile software developer by trade and a photographer by night.

stuff

related tags