Thursday, January 28, 2010

Find the version number of a .class file

If you see the error:
 java.lang.UnsupportedClassVersionError: Bad version number in .class file
it means that the Java ClassLoader cannot load a certain class because it has been compiled using a different version of the JDK. For example, you might see this error if your application has been compiled using Java 1.5, but an external library you are calling has been compiled using 1.6.

You can use the javap command to find out what the version number of a class file is:

sharfah@starship:~> javap -v MyApp | grep version
  minor version: 0
  major version: 50
50 refers to Java 1.6, while 49 refers to Java 1.5.

Tuesday, January 19, 2010

Difference between $*, $@, "$*" and "$@"

They are all related to "all the arguments to the shell", but behave differently. The following script demonstrates each one of $*, $@, "$@" and "$*" in turn by echoing out the arguments passed in:
#! /bin/bash

echo +--- Using "\$*"

cnt=1
for i in $*
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using \"\$*\"

cnt=1
for i in "$*"
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using "\$@"

cnt=1
for i in $@
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using \"\$@\"

cnt=1
for i in "$@"
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done
Running the script, produces the following output:
sharfah@starship:~> echoArgs.sh  mars "kit kat" twix
+--- Using $*
arg1: mars
arg2: kit
arg3: kat
arg4: twix
+--- Using "$*"
arg1: mars kit kat twix
+--- Using $@
arg1: mars
arg2: kit
arg3: kat
arg4: twix
+--- Using "$@"
arg1: mars
arg2: kit kat
arg3: twix
When unquoted, $* and $@ do the same thing. They treat each "word" (sequence of non-whitespace characters) as a separate argument. This leads to the single argument "kit kat" being broken into two which may not be desired. When quoted, $* and $@ behave differently. "$*" treats the entire argument list as a single argument, but "$@" treats the arguments just as they were when passed in.

So, which should you use? In almost all cases you would use "$@" in order to preserve arguments with spaces (or quoted arguments) when being passed in on the command line or from one script to another. Never use the unquoted $* or $@ unless you are absolutely sure that you won't need to deal with arguments with spaces in them. If you need to combine all arguments into one, use "$*".

Monday, January 18, 2010

Java equals() Method

According to the Javadocs, the equals method must be:
  • reflexive: for any non-null reference value x, x.equals(x) should return true.
  • symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • return false for x.equals(null), for any non-null reference value x.
In other words, the following tests must pass:
@Test
public void testEquals() {

  // reflexive
  assertTrue(x.equals(x));

  // symmetric
  assertTrue(x.equals(y) == y.equals(x));

  // transitive
  if (x.equals(y) && y.equals(z)) {
    assertTrue(x.equals(z));
  }

  // consistent
  assertTrue(x.equals(y) == x.equals(y));

  // null check
  assertFalse(x.equals(null));
}
Implementing Equals(): Approach 1
The steps are:
  1. Check reference equality (good optimisation step)
  2. Check correct class type using instanceof
  3. Cast to correct type
  4. Compare objects
@Override
public boolean equals(Object obj) {

  // check reference equality
  if (this == obj) {
    return true;
  }

  // check correct arg type
  if (!(obj instanceof Rectangle)) {
    return false;
  }

  // cast the object to the correct type
  Rectangle other = (Rectangle) obj;

  // compare fields
  return other.getLength() == length &&
         other.getWidth()  == width;
}
But what happens if you extend this class by adding another field? For example, a Rectangle has a length and width. But what if we create a Cuboid that extends Rectangle with an additional depth attribute?

The problem occurs when you mix objects of Rectangle and Cuboid because Rectangle instanceof Cuboid returns false, whereas Cuboid instanceof Rectangle returns true. This breaks the symmetric rule because rectangle.equals(cuboid) is true, but cuboid.equals(rectangle) is false. In order to preserve symmetry, we can change our equals method as follows:

Implementing Equals(): Approach 2

  1. Check if null
  2. Check correct class type using getClass
  3. Cast to correct type
  4. Compare objects
@Override
public boolean equals(Object obj) {

  // check null
  if (obj == null) {
      return false;
  }

  //check correct type
  if(getClass() != obj.getClass()) {
      return false;
  }
  // cast the object to the correct type
  Rectangle other = (Rectangle) obj;

  // compare fields
  return other.getLength() == length &&
         other.getWidth()  == width;
}
The getClass method will always return false if the parameter is not the exact same type as the object class.

In most cases, you should use Approach 2 so that you obey the equals contract, unless you want to compare subclasses with their base types.

Friday, January 15, 2010

Interview Questions

Here are a few questions you may be asked if interviewing for a technology / developer role in an investment bank:

Java:

  • What is object orientation?
  • State three fundamental concepts in object-oriented programming (e.g encapsulation, abstraction, inheritance)?
  • What is the super class of all classes?
  • State three methods of the Object class.
  • What is the difference between checked and unchecked exceptions?
  • Name the subclasses of Throwable.
  • What is the Error class?
  • Why are hashcode() and equals() important?
  • What is hashcode() used for in a Hashmap?
  • Write an equals method for a Person class which contains a String attribute called name.
  • List XML parsers and how would you decide if you should use SAX or DOM?
  • Discuss testing with JUnit.
Oracle:
  • Given an Employee (name, dept_id) table and a Department (id, name) table, write a query to display which department each employee belongs to and another query to list all departments which have exactly 10 employees.
  • What steps would you take to identify why a query is slow and how would you optimise it?
  • What kinds of Hints are there?
  • What is the difference between a normal index and a clustered index?
Problem Solving:
  • You have 8 coins which look identical. However, one of them is heavier than the rest. You have a weighing scale. Find the heaviest coin using the scale the fewest times as possible.
    Answer: Weigh coins 1,2,3 vs 4,5,6. If they weigh the same, weigh 7 vs 8 to get the heaviest. If they are not the same, pick the heaviest batch (e.g. 1,2,3) and weigh 1 vs 2,3 and so on.
  • In the diagram below, you have two lists. Change the ordering of the elements in the first list, so that they appear in the same order as the second list. You have a container which can hold only one element to help you.
  • A          B
    B          C
    C   +--+   D
    D   |  |   E
    E   +--+   F
    F          G
    G          A
    
    Answer: Put A into the container. Shift all elements up by one. Move A into the vacant slot in the bottom of the list.
Risk and PnL:
  • What is Real PnL?
  • What is attribution i.e. what attributes make this PnL?
  • What is explained and unexplained pnl?
  • What is Delta Risk and why is it important?
  • What market data do you need to calculate Delta Risk and how is it calculated?
  • What is a yield curve?
  • What is a volatility surface?
  • Real PnL: Profit and Loss compared to yesterday REAL_P+L = PVToday - PVYest
  • Attribution: What made this PnL such as The Greeks: Delta PnL, Gamma PnL, Theta PnL, Vega PnL, New deals, Dropped deals, Amended deals, Cash flows
  • PnL Explained: The addition of all these attributions that explains the Real PnL.
  • PnL Unexplained: The difference between the Real PnL and the Explained PnL.
  • The target is to get Unexplained as close to 0 as possible.
Related Posts:

Thursday, January 14, 2010

Cobertura - Ignore Logger Calls

I recently caught the testing bug and try to make sure that all the code I write is well tested and has 100% coverage. I use Cobertura, which is an excellent tool for measuring how much of your code is covered by tests. The coverage report it produces shows you what percentage of packages, classes, methods, lines and conditionals are covered and it highlights, in red, the lines in your source code which are not covered. I can now sleep better at night, knowing that my code is fully covered!

In order to use Cobertura, you just need to add the plugin to your project's POM file. When I first ran Cobertura, I found that it highlighted my logger.debug lines of code, so I had to tell it to ignore all logger calls, as follows:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>cobertura-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <formats>
            <format>html</format>
        </formats>
        <instrumentation>
            <ignores>
                <ignore>org.apache.log4j.*</ignore>
            </ignores>
        </instrumentation>
    </configuration>
    <executions>
        <execution>
            <phase>deploy</phase>
            <goals>
                <goal>cobertura</goal>
            </goals>
        </execution>
    </executions>
</plugin>
You can run it using mvn cobertura:cobertura and then look at the report in target/site/cobertura/index.html.

Cobertura will also highlight some code which is impossible to test. For example, if a class has a private constructor (because it has static methods), then it will highlight the private constructor, even though you can't test it (unless you use reflection and change the constructor's accessibility, but that is going a bit too far!).