Java Forum / General / October 2007
How to cast an Object to Double?
www - 17 Oct 2007 15:24 GMT Hi,
I cannot figure out how to do it well. I have an Object, which is retrieved from a map. It actually is a number(double). I need to get its value.
double value = Double.parse((String)theObj); //this works
But:
double value = (Double)theObj; //this does not work in Eclipse, why?
Is that because Double is subclass of Object, similarly a Animal can not be casted into a Cat?
So, I have to cast the Object to String first, then get the double value? (String is a subclass of Object(?). Why the Object can be casted into String?)
Thank you.
Lew - 17 Oct 2007 15:44 GMT > I cannot figure out how to do it well. I have an Object, which is > retrieved from a map. It actually is a number(double). I need to get its [quoted text clipped - 5 lines] > > double value = (Double)theObj; //this does not work in Eclipse, why? It's not Eclipse that decides if this works, it's Java.
> Is that because Double is subclass of Object, similarly a Animal can not > be casted into a Cat? No.
> So, I have to cast the Object to String first, then get the double > value? (String is a subclass of Object(?). No.
> Why the Object can be casted [sic] into String?) Because all Objects have a toString() method. Beware, it might not do what you expect.
This would be easier if you provided an SSCCE <http://www.physci.org/codes/sscce.html> but I'll do my best without one.
Assume a Map declared as
Map <String, Double> stuff = new HashMap <String, Double> ();
Later some code does:
Double d = stuff.get( key );
where key is some String. No casting needed.
If for some reason you were to use
Object o = stuff.get( key );
then you need to cast the return value, but that should work since you know the map values are Double.
The only way I can imagine you getting the result you state, absent an SSCCE, is that you used a raw Map type and inserted a non-Double into the value.
Provide an SSCCE and we'll see how close my guesses came.
 Signature Lew
RedGrittyBrick - 17 Oct 2007 16:09 GMT > Hi, > > I cannot figure out how to do it well. I have an Object, I try to avoid using Objects unless the API forces me.
> which is retrieved from a map. What sort of map? Some implementation of java.util.Map?
If it's something like HashMap then the problem could be made to go away by using generics.
Map m = new HashMap<String, Double>(); m.put("hatsize", new Double(23.45)); ... double value = m.get("hatsize");
Note that Java will "autobox" Double and double. I usually use a static constant or enum value in place of Strings like "hatsize", but I'm digressing.
> It actually is a number(double). I need to get its > value. [quoted text clipped - 11 lines] > value? (String is a subclass of Object(?). Why the Object can be casted > into String?) I try to avoid explicit casting. Making more use of generics is one way I do this.
Lew - 17 Oct 2007 16:13 GMT > If it's something like HashMap then the problem could be made to go away > by using generics. > Map m = new HashMap<String, Double>(); nitpicking: Map<String, Double> m = new HashMap<String, Double>();
 Signature Lew
RedGrittyBrick - 17 Oct 2007 16:18 GMT >> If it's something like HashMap then the problem could be made to go >> away by using generics. >> Map m = new HashMap<String, Double>(); > > nitpicking: > Map<String, Double> m = new HashMap<String, Double>(); Oops, thanks for the correction!
www - 17 Oct 2007 17:02 GMT OK. My full testing program is:
public class HelloWorld {
public static void main( String[] args ) { Map<String, Object> map = new HashMap<String, Object>(10); Properties states = new Properties(); try { states.load(new FileInputStream("property_file.txt")); } catch(IOException e) { } //copy entries from states file to the map for (Map.Entry value : states.entrySet()) { map.put((String)value.getKey(), value.getValue()); } Object obj = map.get("HAT_SIZE"); double value = (Double)obj; //causing error!!!!!!!! I don't understand why.
//following is ok, but why need to cast to String first? double value = Double.parse((String)obj); }
}
The property file("property_file.txt") has the content: HAT_SIZE=5.999 SHOE_SIZE=3.23
Thank you for your help.
mrnohr - 17 Oct 2007 17:46 GMT > double value = (Double)obj; //causing error!!!!!!!! I don't understand why. Try this: double value = ((Double)obj).doubleValue();
Double (with a capital D) is a wrapper class and double (lower case d) is a primitive datatype. This casts the object as a Double then gets the primitive datatype from that.
www - 17 Oct 2007 18:03 GMT >> double value = (Double)obj; //causing error!!!!!!!! I don't understand why. > [quoted text clipped - 4 lines] > is a primitive datatype. This casts the object as a Double then gets > the primitive datatype from that. I have just tried it. It does not work.
Actually, I believe the following two are the same thing.
double value = (Double)obj; double value = ((Double)obj).doubleValue();
The first one will automatically convert a Double object to a double value and assign it to variable value.
Mark Rafn - 17 Oct 2007 18:16 GMT >OK. My full testing program is: > [quoted text clipped - 37 lines] >HAT_SIZE=5.999 >SHOE_SIZE=3.23 Good. One improvement would be for your test to actually compile (i.e. include necessary imports, and leave the duplicate working line commented out. More importantly, if you're getting an error, TELL US what it is! When I read your post, I thought you were getting a compile error, and I couldn't see why - you're allowed to cast an Object to a Double.
It turns out you're NOT getting a compile error, you're getting a runtime error, and it is Exception in thread "main" java.lang.ClassCastException: java.lang.String at Foo.main(Foo.java:28) This means you're trying to cast a String into a Double. That won't work.
Casting is different than parsing. Casting is just a way to tell one part of the code that you, the developer, have more information about the type of the object, and you want to try to use the object as if it were this more specific type. If it's NOT actually usable as that type, it'll get a ClassCastException.
A String isn't a Double. It's a String. So the cast fails.
What you want is to parse the string, meaning to read it's characters and see what double it represents. You can do that by using the Double.parseDouble(String) method. It takes a string, so if you know the object is a String, you can cast it. That's your double value = Double.parseDouble((String)obj); line (note that it's parseDouble(), not parse()).
If you don't know that, you can call toString() on it. double value = Double.parseDouble(obj.toString());
If you want a Double object rather than a double primitive value, you can use Double value = new Double((String)obj);
Of course, many Strings, and even more non-String objects, have string values that can't be parsed, and you'll get a NumberFormatException. -- Mark Rafn dagon@dagon.net <http://www.dagon.net/>
www - 17 Oct 2007 19:01 GMT you're getting a runtime
> error, and it is > Exception in thread "main" java.lang.ClassCastException: java.lang.String [quoted text clipped - 8 lines] > > A String isn't a Double. It's a String. So the cast fails. Thank you so much for your reply. I still don't understand:
<java> //copy entries from states file to the map for (Map.Entry value : states.entrySet()) { map.put((String)value.getKey(), value.getValue()); //I thought it is String-Object pair!!! } <java>
Then, you are saying:
map.get("HAT_SIZE") is a String, that is why (Double)map.get("HAT_SIZE") will fail. (A String cannot be casted to a Double).
I thought map.get("HAT_SIZE") is an Object, due to the map Generics definition. If so, (Double)map.get("HAT_SIZE") should work.
I think:
map.put((String)value.getKey(), value.getValue());
is the one causing all the trouble and confusion. The values in the map are a bunch of String, not Object. But why they are not Object? value.getValue() is Object.
The map definition(Map<String, Object> map = new HashMap<String, Object>(10)) also show that the value is Object type.
Christian - 17 Oct 2007 19:29 GMT www schrieb:
> you're getting a runtime >> error, and it is Exception in thread "main" [quoted text clipped - 43 lines] > The map definition(Map<String, Object> map = new HashMap<String, > Object>(10)) also show that the value is Object type. the problem ist not that they are not Object the problem is that they are not Double..
you may only cast to Double what is of instance Double (means is Double or extends double)
you can cast an animal to cat if it is a cat but you can't cast an animal to dog if it is a cat, although it is also an animal..
Mark Rafn - 17 Oct 2007 20:18 GMT ><java> > //copy entries from states file to the map [quoted text clipped - 4 lines] > } ><java> Map by itself is Object-Object. You specified <String, Object>, so the compiler will enforce that for you as a convenience.
"HAT_SIZE" is a String, and is a fine key. "5.999" is a String as well. Since a String is an Object, that's an allowable value in your map.
>map.get("HAT_SIZE") is a String, that is why (Double)map.get("HAT_SIZE") >will fail. (A String cannot be casted to a Double). You're using the String "HAT_SIZE" as a key. You're getting an Object "5.999" which you, as a developer, know is a String, but the compiler doesn't. So you have to cast it when you want to do something that requires it to be a String rather than the more generic Object.
You can cast the Object "5.999" to a String, because it is. You can tell the VM to cast it to a Double, but it'll fail when it tries, because it's not a Double.
>I thought map.get("HAT_SIZE") is an Object, due to the map Generics >definition. If so, (Double)map.get("HAT_SIZE") should work. Do you think Double d = (Double)"5.999"; would work? I don't. "5.999" is a string, not a number. You have to parse it to get it's numeric value.
Note: if you'd declared your map to be <String, Double>, you'd have caught this mistake earler, as the map.put() line would not have compiled. The compiler would know you're trying to put a String into a Double value. -- Mark Rafn dagon@dagon.net <http://www.dagon.net/>
Mark Space - 18 Oct 2007 00:18 GMT > I thought map.get("HAT_SIZE") is an Object, due to the map Generics > definition. If so, (Double)map.get("HAT_SIZE") should work. No. Java objects retain their type, always. They are never coverted to anything else my casting. They always retain their type. The Double object has a big old stamp on it that says "This is a Double." When you cast, Java just looks at that stamp and says "Is it a Double?" If the stamp says "String" instead, you get an error.
Object just tells the compiler what types to check. The cast has to be supplied to the right type of object.
Even though the map says "Object" their types never change. It just means the map will accept anything.
Patricia Shanahan - 18 Oct 2007 01:45 GMT ...
> The map definition(Map<String, Object> map = new HashMap<String, > Object>(10)) also show that the value is Object type. There are two issues that are combined here, and are better kept separate:
1. The class of an object. The class of each object is specified when it is created, either new or by cloning an existing object. It cannot be changed during the object's life.
2. The type of a variable or expression. The type of a variable or expression can be calculated at compile time.
A reference expression can point to some object if, and only if, the type of the expression corresponds to the object's class, or to one of its superclasses, or one of the interfaces it implements.
During an object's life, it may be referenced by expressions of any appropriate type. Similarly, an expression may reference objects of different classes at different times.
Object is the ultimate superclass, so an Object expression, such as the result of get on a Map<String,Object> can reference ANY object, regardless of its class. In this case, it happens to point to a String.
That String remains a String, regardless of whether the type of the referencing expression is Object, String, Serializable, CharSequence, or Comparable<String>.
Patricia
RedGrittyBrick - 17 Oct 2007 23:58 GMT > OK. My full testing program is: > [quoted text clipped - 9 lines] > { > states.load(new FileInputStream("property_file.txt")); This loads the values as type String.
> } > catch(IOException e) { [quoted text clipped - 6 lines] > map.put((String)value.getKey(), value.getValue()); > } I'm not sure why you are copying a HashTable backed Properties object into a new HashMap. Surely you could just use "states" where you later use "map"?
> > > Object obj = map.get("HAT_SIZE"); > > double value = (Double)obj; //causing error!!!!!!!! I don't > understand why. Because obj is a String, you can't cast a String to a Double.
> //following is ok, but why need to cast to String first? > double value = Double.parse((String)obj); Because the compiler doesn't know the type of obj, you told the compiler that obj was an Object, it doesn't know that obj will hold a String at run-time.
> > [quoted text clipped - 5 lines] > HAT_SIZE=5.999 > SHOE_SIZE=3.23 Note that 5.999 is a String even if it doesn't look like it.
> Thank you for your help. I'd rethink the approach to avoid all mention of type "Object".
e.g. one step along that path ...
public class PropertyDouble { public static void main(String[] args) throws FileNotFoundException, IOException {
Properties states = new Properties(); states.load(new FileInputStream("property_file.txt"));
// copy entries from states file to the map Map<String, Double> map = new HashMap<String, Double>(10); for (Map.Entry entry : states.entrySet()) { String key = (String) entry.getKey(); Double value = Double.parseDouble( (String) entry.getValue()); map.put(key, value); }
double value = map.get("HAT_SIZE");
System.out.println("Double : " + Double.toString(value)); } }
RedGrittyBrick - 18 Oct 2007 00:18 GMT Maybe this makes it clearer ...
public class PropertyDouble { public static void main(String[] args) throws FileNotFoundException, IOException {
Properties states = new Properties(); states.load(new FileInputStream("property_file.txt"));
// copy entries from states file to the map Map<String, Double> map = new HashMap<String, Double>(10); for (Map.Entry entry : states.entrySet()) {
Object keyObj = entry.getKey(); if (keyObj instanceof String) { System.out.println("Key is a String"); } String key = (String) keyObj;
Object valueObj = entry.getValue(); if (valueObj instanceof String) { System.out.println("Value is a String"); } String valueString = (String) valueObj; Double value = Double.parseDouble(valueString);
map.put(key, value); }
double value = 2.54 * map.get("HAT_SIZE"); System.out.printf("Metric : %.4f \n", value); } }
Lew - 18 Oct 2007 00:35 GMT > Maybe this makes it clearer ... > [quoted text clipped - 4 lines] > Properties states = new Properties(); > states.load(new FileInputStream("property_file.txt")); One would be safer using a FileReader.
> // copy entries from states file to the map Since you already pointed out:
>> I'm not sure why you are copying a HashTable backed Properties object into a new HashMap. >> Surely you could just use "states" where you later use "map"? we could skip that copy. (It's actually a mistake Sun made having Properties extend Hashtable.) I know you show it in order to make the points about conversion, but let's take a look at what life is like without the copy:
Continuing the code snippet:
> double value = 2.54 * Double.parseDouble( states.getProperty( "HAT_SIZE" )); > System.out.printf("Metric : %.4f \n", value); > } > }
 Signature Lew
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|