All 29 entries tagged Java
View all 241 entries tagged Java on Warwick Blogs | View entries tagged Java at Technorati | There are no images tagged Java on this blog
June 21, 2006
How little I know ;)
Writing about web page http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
I was having a technical chat with Rob Harrop of Interface21 fame and we got talking about java synchronisation and the farce that is double checked locking, both concepts I thought I had a handle on.
Anyways, I decided to do a bit more reading and am astounded at how much I don't know :) Admittedly I don't feel too bad about this because I have never explicitly looked at these in depth, but here are some interesting links:
I thought I knew quite a bit about java until I spoke to Rob :)
April 20, 2006
Crappy java.sql.Timestamp pretending to be java.util.Date
So I started getting ClassCastExceptions when comparing two java.util.Dates. Tracking it down, I realised (and in fact the stack trace told me) that one of the java.util.Dates was actually a java.sql.Timestamp. So looking at the code, I was a bit surprised to realise that I was actually casting the objects to java.util.Date….which is valid because java.sql.Timestamp extends java.util.Date.
So why doesn't it work, and whose fault is it?
On the face of it, it would appear java.util.Timestamp is at fault because it is a java.util.Date and should therefore be able to be used in place of a java.util.Date; quite a fundamental OO rule (substitution). But then thinking a bit more, I realised it isn't quite so clear cut... The substitution rule states that you must be able to use any subclass in place of it's parent, but it doesn't state that the sub class must behave exactly like it's parent...which is obvious when you think about it. If this wasn't the case, you would never be allowed to change the behaviour of any of the methods. Arguably, you should never make the behaviour inconsistent with the intention of the super classes' method.
In otherwords, java.util.Date.compareTo(java.util.Timestamp) must work, but there is no guarantee that java.util.Timestamp.compareTo(java.util.Date) needs to work..
And in fact, it was java.sql.Timestamp.compareTo(java.util.Date) was throwing the exception.
So it seems java.sql.Timestamp is technically correct, even if it isn't very friendly :(
Still think it is wrong, but not sure it is technically wrong…..
February 13, 2006
helloworld annotation
So I wanted to play around with Annotations, so I decided to do a hello world.
Actually, the use case is I wanted to mark hibernate backed objects as needing to be autowired by Spring.
I created my annotation
public @interface Autowired {
}
and updated my class:
@Autowired public class MyClass {
}
and nothing. The unit test failed:
MyClass cf = new MyClass();
Class class1 = cf.getClass();
// assertTrue(class1.isAnnotationPresent(Autowired.class));
Annotation[] anns = class1.getAnnotations();
assertEquals(1, anns.length);
No idea why, thinking it might be a class path issue with Eclipse, I recompiled, but still nothing.
As it turns out, you need to annotate your annotations :) You need to tell the compiler how to retain the annotations (link).
Specifying that the annotations must be retained for runtime retrieval means it now works:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
The Target BTW restricts this annotation so it can only be applied to a class.
Very useful stuff :)
February 06, 2006
Java Pet Peeves #2:Useless assignments
Boy; am I moaning today :)
So my second pet peeve is unnecessary assignments within Java.
Essentially; all member variables will be assigned to a default value (Object=null, int=0, boolean=false), whilst all local variables will have no initialisation.
Thus, the following two classes will be equivalent:
public class ClassThatUnderstandsHowJavaWorks {
private Object o;
private boolean b;
private int i;
}
public class ClassThatDoesntUnderstandHowJavaWorks {
private Object o = null;
private boolean b = false;
private int i = 0;
}
I have heard the argument that the second form is more explicit. I don't but this because it means every time you write a member variable you need to write extra crud. Every time! It would be far better to educate people once and write neat code, than write bad code over and over.
The other aspect of initialisation is allowing the compiler to help you. For example, if you have a variable which should always be initialised within an if clause, how many people would write:
String message = null;
if (someCondition) {
message = "a message";
} else (someOtherCondition) {
message = "some other message";
}
This code will compile, and work; but will allow the situation for message to be null (if neither condition is used). If the assumption is that one of the two conditions will always be true, the compiler cannot help you.
Remove the initial initialisation and the code won't compile:
String message;
if (someCondition) {
message = "a message";
} else (someOtherCondition) {
message = "some other message";
}
because the compiler will catch the fact that there is a route through your code that will leave message in an uninitialised state. Forcing you to rethink your if condition.
Java Pet Peeves #1:Pointless Constructors
So I was looking through some code (the author shall remain nameless :)) and spotted a shed load of my number #1 pet peeve; useless constructors:
public class Something {
public void aMethod() {
…
}
}
In the above circumstance there is absolutely no point (as far as the JRE is concerned) to put a default constructor. The following will result in exactly the same byte code (I imagine; I cannot verify this :)):
public class Something {
public Something() {
super();
}
public void aMethod() {
…
}
}
or even worse:
public class Something {
public class Something() {
}
public void aMethod() {
…
}
}
Why, oh why must people do it?
Admittedly; stupidly Eclipse provides a default constructor (with the super() call) by default, but that is no excuse.
It is quite simple; if you have no constructors, the JDK will provide a default constructor which contains a call to super() for you. You must provide a constructor if either you do not wish to have a default constructor, or the super class does not include one.
For example, if you have a class which requires a number of collaborators to work, then you should create a constructor which takes in those collaborators. Because you have provided a constructor, the JDK won't put a default one in for you, so:
public class Something {
public Something(final String s) {
}
public void aMethod() {
…
}
}
can be instantiated with:
new Something("ssss"); // good
new Something(); // bad
The JDK cannot create a default constructor if the super class doesn't itself contain a default constructor:
public class BaseClass {
}
public class ExtendedClass extends BaseClass {
// no need to put a constructor
}
public class BaseClass {
public BaseClass() {
// stupid, but used for illustrative purposes.
}
}
public class ExtendedClass extends BaseClass {
// still no need to put a constructor
}
however:
public class BaseClass {
public BaseClass(final String s) {
}
}
public class ExtendedClass extends BaseClass {
// absolutely must put a constructor in, even if it is a no-args constructor
public ExtendedClass() {
super("some value");
}
}
So please; when you create the next class, ask yourself whether it requires any collaborators, if it does, provide a single constructor with those collaborators (which should be marked final BTW :)). If it doesn't, don't provide any constructors; let the JDK do it's job.
And if you must provide a constructor; make sure you call super(...) :)
Please, for my sanity :)
February 03, 2006
OK; I confess
Follow-up to The value of being explicit…. from Colin's blog
OK, OK: the original code actually used a Map instead of a Set.
For some reason I never used Set's; I would always use a Map and then Map.contains().
It is only in the last few years I started using a Set.
There, go and laugh now :)
I don't know; you just can get the senior staff nowadays :)
Come one; share the fun; what cringeworthy things do you do?
JDK5 Annotations; I love them, no, I hate them! (Actually I hate Eclipse) :)
So there is a fantastically useful annotation: @Override which when indicates that a particular method is overriding a method in the super class.
Why is this useful?
Assume today we are overriding the method called "methodA", tomorrow we get a new release of the library and the method in the parent class is no longer called "methodA", but renamed to "methodWithAMuchBetterName".
Your code is syntactically correct; it will compile, but it is not semantically correct. The no longer overridden method fails. No compiler errors to help you out; nothing.
You may argue that if you are overridding a method you almost certainly want to be calling super.sameMethod(); but that is just wrong. You do not have to , nothing in the million + 1 best practices suggest it, it is one of the more annoying anti-patterns. In particular; a lot of framework provide template method which do absolutely nothing for the sole purpose of you extending them; or they provide abstract methods for the same purpose.
Anyways; so JDK5 introduced an Annotation which told the compiler that the method is overridding a parent method. If the method in the super class is removed; your code won't compile.
Excellent. Lovely. As well as adding extra documentation to the source code; it has empowering side effects.
So sure; I love JDK annotations.
Now I implement an interface; create a method which implements the interface, stick an "@Override" on the method, and what happens? Eclipse moans that the method must override a superclass method.
ARRRGGHHH!!!!! It still compiles, but the source code looks like it is incorrect code.
Poo.
The value of being explicit….
So I had to explain some code I wrote a year or so ago to the colleague who was maintaing it and it looked something like this:
public CollaboratorA doSomething() {
final Set data = new HashSet();
// .. populate the data
return new CollaboratorA {
boolean isThisTrueForSomeCriteria(final Object o) {
return data.contains(o);
}
}
}
which is all perfectly valid; but not at all intuitive. In particular; what was the lifetime of Set data?
I then rewrote this and moved the inner class into it's explicit class:
public CollaboratorA doSomething() {
final Set data = new HashSet();
// .. populate the data
return new SetBackedCollaboratorA(data);
}
class SetBackedCollaboratorA implements CollaboratorA {
private final Set data;
SetBackedCollaboratorA(final Set theData) {
this.data = theData;
}
boolean isThisTrueForSomeCriteria(final Object o) {
return data.contains(o);
}
}
and this was found to be much easier to understand even though under the hood there is absolutely no difference. I am not entirely sure whether the byte code would even be any different, but the intuitiveness or readability was improved; so it was a win :)
To be clear; it was not the use an an inner class that was confusing; it was the fact that an inner class was referencing a variable defined in the method, outside of the method that created the inner class and the data.
Lesson for the day (because I keep needing to learn it again ;)); code that is functional is not as valuable as code that is intuitively functional.
January 30, 2006
Utterly underwhelming ;)
Follow-up to Spring User Group (or maybe just general Java); interested? from Colin's blog
No one?
Come on guys/gals; I know there are a lot of techies out there…. you can't hide forever :)
January 26, 2006
Spring User Group (or maybe just general Java); interested?
Hi one and all,
I am interested in finding/starting a Spring (www.springframework.org) User Group, or maybe just a general Java User Group.
Idea would be to meet regularly (maybe monthly), discuss latest framework/Java developments, demonstrations of cool code, questions (and hopefully answers) and most importantly, eat lots of pizza.
Anyone interested?
Let me know please :)