From 3daf5859318d6c1f2d9b6a537115d4235533c0ef Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Sat, 26 Sep 2015 17:58:13 -0700 Subject: [PATCH 1/3] Implemented equals and hashcode for LazilyParsedNumber to fix https://github.com/google/gson/issues/627 --- .../gson/internal/LazilyParsedNumber.java | 176 ++++++++++-------- .../gson/internal/LazilyParsedNumberTest.java | 32 ++++ 2 files changed, 131 insertions(+), 77 deletions(-) create mode 100644 gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java diff --git a/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java b/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java index 37ee5035..a660af08 100644 --- a/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java +++ b/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java @@ -1,78 +1,100 @@ -/* - * Copyright (C) 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.gson.internal; - -import java.io.ObjectStreamException; -import java.math.BigDecimal; - -/** - * This class holds a number value that is lazily converted to a specific number type - * - * @author Inderjeet Singh - */ -public final class LazilyParsedNumber extends Number { - private final String value; - - public LazilyParsedNumber(String value) { - this.value = value; - } - - @Override - public int intValue() { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - try { - return (int) Long.parseLong(value); - } catch (NumberFormatException nfe) { - return new BigDecimal(value).intValue(); - } - } - } - - @Override - public long longValue() { - try { - return Long.parseLong(value); - } catch (NumberFormatException e) { - return new BigDecimal(value).longValue(); - } - } - - @Override - public float floatValue() { - return Float.parseFloat(value); - } - - @Override - public double doubleValue() { - return Double.parseDouble(value); - } - - @Override - public String toString() { - return value; - } - - /** - * If somebody is unlucky enough to have to serialize one of these, serialize - * it as a BigDecimal so that they won't need Gson on the other side to - * deserialize it. - */ - private Object writeReplace() throws ObjectStreamException { - return new BigDecimal(value); - } +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.gson.internal; + +import java.io.ObjectStreamException; +import java.math.BigDecimal; + +/** + * This class holds a number value that is lazily converted to a specific number type + * + * @author Inderjeet Singh + */ +public final class LazilyParsedNumber extends Number { + private final String value; + + public LazilyParsedNumber(String value) { + this.value = value; + } + + @Override + public int intValue() { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + try { + return (int) Long.parseLong(value); + } catch (NumberFormatException nfe) { + return new BigDecimal(value).intValue(); + } + } + } + + @Override + public long longValue() { + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + return new BigDecimal(value).longValue(); + } + } + + @Override + public float floatValue() { + return Float.parseFloat(value); + } + + @Override + public double doubleValue() { + return Double.parseDouble(value); + } + + @Override + public String toString() { + return value; + } + + /** + * If somebody is unlucky enough to have to serialize one of these, serialize + * it as a BigDecimal so that they won't need Gson on the other side to + * deserialize it. + */ + private Object writeReplace() throws ObjectStreamException { + return new BigDecimal(value); + } + + @Override + public int hashCode() { + return value == null ? 0 : value.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || !(obj instanceof LazilyParsedNumber)) { + return false; + } + LazilyParsedNumber other = (LazilyParsedNumber) obj; + return equals(value, other.value); + } + + private static boolean equals(Object obj1, Object obj2) { + if (obj1 == null) return obj2 == null; + return obj1 == obj2 || obj1.equals(obj2); + } } \ No newline at end of file diff --git a/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java b/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java new file mode 100644 index 00000000..518e2e08 --- /dev/null +++ b/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.gson.internal; + +import junit.framework.TestCase; + +public class LazilyParsedNumberTest extends TestCase { + public void testHashCode(){ + LazilyParsedNumber n1 = new LazilyParsedNumber("1"); + LazilyParsedNumber n1Another = new LazilyParsedNumber("1"); + assertEquals(n1.hashCode(), n1Another.hashCode()); + } + + public void testEquals(){ + LazilyParsedNumber n1 = new LazilyParsedNumber("1"); + LazilyParsedNumber n1Another = new LazilyParsedNumber("1"); + assertTrue(n1.equals(n1Another)); + } +} From 3aec17324366eba5fc935d9b7d1073208f0bff30 Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Sat, 26 Sep 2015 18:02:12 -0700 Subject: [PATCH 2/3] small reformatting --- .../gson/internal/LazilyParsedNumber.java | 200 +++++++++--------- .../gson/internal/LazilyParsedNumberTest.java | 4 +- 2 files changed, 102 insertions(+), 102 deletions(-) diff --git a/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java b/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java index a660af08..0372ec6e 100644 --- a/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java +++ b/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java @@ -1,100 +1,100 @@ -/* - * Copyright (C) 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.gson.internal; - -import java.io.ObjectStreamException; -import java.math.BigDecimal; - -/** - * This class holds a number value that is lazily converted to a specific number type - * - * @author Inderjeet Singh - */ -public final class LazilyParsedNumber extends Number { - private final String value; - - public LazilyParsedNumber(String value) { - this.value = value; - } - - @Override - public int intValue() { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - try { - return (int) Long.parseLong(value); - } catch (NumberFormatException nfe) { - return new BigDecimal(value).intValue(); - } - } - } - - @Override - public long longValue() { - try { - return Long.parseLong(value); - } catch (NumberFormatException e) { - return new BigDecimal(value).longValue(); - } - } - - @Override - public float floatValue() { - return Float.parseFloat(value); - } - - @Override - public double doubleValue() { - return Double.parseDouble(value); - } - - @Override - public String toString() { - return value; - } - - /** - * If somebody is unlucky enough to have to serialize one of these, serialize - * it as a BigDecimal so that they won't need Gson on the other side to - * deserialize it. - */ - private Object writeReplace() throws ObjectStreamException { - return new BigDecimal(value); - } - - @Override - public int hashCode() { - return value == null ? 0 : value.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || !(obj instanceof LazilyParsedNumber)) { - return false; - } - LazilyParsedNumber other = (LazilyParsedNumber) obj; - return equals(value, other.value); - } - - private static boolean equals(Object obj1, Object obj2) { - if (obj1 == null) return obj2 == null; - return obj1 == obj2 || obj1.equals(obj2); - } -} \ No newline at end of file +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.gson.internal; + +import java.io.ObjectStreamException; +import java.math.BigDecimal; + +/** + * This class holds a number value that is lazily converted to a specific number type + * + * @author Inderjeet Singh + */ +public final class LazilyParsedNumber extends Number { + private final String value; + + public LazilyParsedNumber(String value) { + this.value = value; + } + + @Override + public int intValue() { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + try { + return (int) Long.parseLong(value); + } catch (NumberFormatException nfe) { + return new BigDecimal(value).intValue(); + } + } + } + + @Override + public long longValue() { + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + return new BigDecimal(value).longValue(); + } + } + + @Override + public float floatValue() { + return Float.parseFloat(value); + } + + @Override + public double doubleValue() { + return Double.parseDouble(value); + } + + @Override + public String toString() { + return value; + } + + /** + * If somebody is unlucky enough to have to serialize one of these, serialize + * it as a BigDecimal so that they won't need Gson on the other side to + * deserialize it. + */ + private Object writeReplace() throws ObjectStreamException { + return new BigDecimal(value); + } + + @Override + public int hashCode() { + return value == null ? 0 : value.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || !(obj instanceof LazilyParsedNumber)) { + return false; + } + LazilyParsedNumber other = (LazilyParsedNumber) obj; + return equals(value, other.value); + } + + private static boolean equals(Object obj1, Object obj2) { + if (obj1 == null) return obj2 == null; + return obj1 == obj2 || obj1.equals(obj2); + } +} diff --git a/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java b/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java index 518e2e08..f108fa0d 100644 --- a/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java +++ b/gson/src/test/java/com/google/gson/internal/LazilyParsedNumberTest.java @@ -18,13 +18,13 @@ package com.google.gson.internal; import junit.framework.TestCase; public class LazilyParsedNumberTest extends TestCase { - public void testHashCode(){ + public void testHashCode() { LazilyParsedNumber n1 = new LazilyParsedNumber("1"); LazilyParsedNumber n1Another = new LazilyParsedNumber("1"); assertEquals(n1.hashCode(), n1Another.hashCode()); } - public void testEquals(){ + public void testEquals() { LazilyParsedNumber n1 = new LazilyParsedNumber("1"); LazilyParsedNumber n1Another = new LazilyParsedNumber("1"); assertTrue(n1.equals(n1Another)); From 96b2ada79aeaa44e4c572b345563d0ee90dde5b1 Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Sun, 27 Sep 2015 13:58:01 -0700 Subject: [PATCH 3/3] incorporated code review feedback: optimized LazilyParsedNumber.equals/hashcode() by utilizing the fact that value is never passed as null. --- .../google/gson/internal/LazilyParsedNumber.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java b/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java index 0372ec6e..3669af7b 100644 --- a/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java +++ b/gson/src/main/java/com/google/gson/internal/LazilyParsedNumber.java @@ -26,6 +26,7 @@ import java.math.BigDecimal; public final class LazilyParsedNumber extends Number { private final String value; + /** @param value must not be null */ public LazilyParsedNumber(String value) { this.value = value; } @@ -78,7 +79,7 @@ public final class LazilyParsedNumber extends Number { @Override public int hashCode() { - return value == null ? 0 : value.hashCode(); + return value.hashCode(); } @Override @@ -86,15 +87,10 @@ public final class LazilyParsedNumber extends Number { if (this == obj) { return true; } - if (obj == null || !(obj instanceof LazilyParsedNumber)) { - return false; + if (obj instanceof LazilyParsedNumber) { + LazilyParsedNumber other = (LazilyParsedNumber) obj; + return value == other.value || value.equals(other.value); } - LazilyParsedNumber other = (LazilyParsedNumber) obj; - return equals(value, other.value); - } - - private static boolean equals(Object obj1, Object obj2) { - if (obj1 == null) return obj2 == null; - return obj1 == obj2 || obj1.equals(obj2); + return false; } }