3

I have a Value Class and there is an Object value in it. I want to use the value as String, Integer or Double.

The asDouble method controls instanceof value object. If it is not Double or Integer returns 0.

Generally it works but sometimes although it is Double returns 0;. I couldn't the reason of it.

When I debug I can see:

you can check

Here is my Value class

public class Value{
    public Object value;

    public Value(Object value) {
        this.value = value;
    }

    public Double asDouble() {
        if (this.value instanceof Integer || this.value instanceof Double) {
            return Double.parseDouble(String.valueOf(this.value));
        } else {
            return 0.0; 
        }
    }
}

Could anybody explain where did I go wrong

7
  • 5
    Two possibilities come to mind: You've got a class called Double somewhere that isn't java.lang.Double or you've got multithreaded code modifying value while you read it. Commented Apr 16, 2018 at 14:57
  • 2
    Can you create a minimal reproducible example? You are missing the input data that leads to this "bug", we need it to reproduce the issue. Otherwise we can only guess what the reason is. Probably you only thought you entered a Double to value, but did enter a different object. Like a String maybe "0.2" instead of just 0.2. Commented Apr 16, 2018 at 15:00
  • 5
    From your image it may seem that you have happened to nest two Value objects inside each other, only the inner one containing a Double. So this.value is a Value, not a Double, so the else part is executed. Commented Apr 16, 2018 at 15:14
  • 2
    Instead of checking explicitly for the types Integer or Double, you could just check if it is Number then call .doubleValue() to get the value as a double. Commented Apr 16, 2018 at 15:18
  • 1
    @OleV.V. agree - a Value instance inside another Value indeed seems to be what's shown in the hover. Commented Apr 16, 2018 at 15:38

3 Answers 3

5

Short Answer: Details matter.

Some info: The value class instance variable (also-known-as property or member variable) is a class named Value. Since the class Value is neither the Integer nor the Double class, the else branch will always execute.

The Value class also has a member variable named value, which, in your example, has a type of Double.

In the screen shot you included, the Value object has its value member variable set to a "thing" which also has the type Value. I know this because the dialog shows "value= Value (id:82)".

Sign up to request clarification or add additional context in comments.

Comments

2

first at all, i agree with Ole V.V.s, killjoys and david as comments.

your screenshot shows a Value-Object holding another Value-Object in its value-property

the comments and a possible solution are summed up in the following example-class

public class Value {
    // visibility should be private
    private final Object value;

    // to be more type-save 
    // and to restrict
    // this.values instance-type to Double, Integer and/or String
    // provide three public constructors
    public Value(final Double value) {
        this.value = value;
    }

    public Value(final Integer value) {
        this.value = value;
    }

    public Value(final String value) {
        this.value = value;
    }

    public double asDoublePrimitive() {
        if ((this.value instanceof Number)) {
            return ((Number) this.value).doubleValue();
        }
        return 0.0;
    }

    public Double asDoubleObject() {
        if ((this.value instanceof Number)) {
            return Double.valueOf(((Number) this.value).doubleValue());
        }
        return Double.valueOf(0.0);
    }
}

be aware that neither your nor my code consider the case that this.value is an instanceof String

1 Comment

There's an unnecessary object creation in asDoubleObject() in the case when value instanceOf Double. In that case, I would simply return (Double) value.
1

instanceof check applies to full class definiton which includes the ClassLoader that loaded the class. Probably this.value was loaded by different ClassLoader and the check fails. You can confirm by trying:

ClassLoader cl1 = this.value.getClass().getClassLoader()
ClassLoader cl2 = Double.class.getClassLoader();
if (cl1.equals(cl2)) {
   ...
}

Although this can get even more trickier with parent-child relationships between ClassLoader objects this answer provides a good example when instanceof fails.

The other options is that your Double is not a java.lang.Double but that would be surprising.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.