It's not particularly well-explained by the documentation, but Double.toString(double) essentially performs some rounding in the output it produces. The Double.toString algorithm is used all throughout Java SE, including e.g. PrintStream.println(double) of System.out. The documentation says this:
How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0.
In other words, it says that the return value of toString is not necessarily the exact decimal representation of the argument. The only guarantee is that (roughly speaking) the argument is closer to the return value than any other double value.
So when you do something like System.out.println(1.10) and 1.10 is printed, this does not mean the value passed in is actually equivalent to the base 10 value 1.10. Rather, essentially the following happens:
- First, during compilation, the literal 1.10is examined and rounded to produce the nearestdoublevalue. (It says in the JLS here the rules for this are e.g. detailed inDouble.valueOf(String)fordouble.)
- Second, when the program runs, Double.toStringproduces aStringrepresentation of some decimal value which thedoublevalue produced in the previous step is closer to than any otherdoublevalue.
It just so happens that conversion to String in the second step often produces a String which is the same as the literal in the first step. I'd assume this is by design. Anyhow though, the literal e.g. 1.10 does not produce a double value which is exactly equal to 1.10.
You can discover the actual value of a double (or float, because they can always fit in a double) using the BigDecimal(double) constructor:
When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method. 
// 0.899999999999999911182158029987476766109466552734375
System.out.println(new BigDecimal((double) ( 2.00 - 1.10 )));
// 0.89999997615814208984375
System.out.println(new BigDecimal((float)  ( 2.00 - 1.10 )));
You can see that neither result is actually 0.9. It's more or less just a coincidence that Float.toString happens to produce 0.9 in that case and Double.toString does not.
As a side note, (double) (2.00 - 1.10) is a redundant cast. 2.00 and 1.10 are already double literals so the result of evaluating the expression is already double. Also, to subtract float, you need to cast both operands like (float) 2.00 - (float) 1.10 or use float literals like 2.00f - 1.10f. (float) (2.00 - 1.10) only casts the result to float.