简体   繁体   中英

How to instantiate a generic class that extends Number with a given double value?

Suppose I have this Foo class, which has generic type variable E that extends Number . Since each Number object should have a double value, when instantiating a new instance of type E I would like to give it a double value. Is it possible? How?

public class Foo<E extends Number> {
    ...
    public void someMethod() {
        ... // some computation
        Class<E> typeClass;
        E newInstance = typeClass.newInstance();
        // Because every Number has a doubleValue(),
        // I would like to give newInstance a double value, how?
    }
}

Or should I just abandon the generic type variable, and use Double instead? But I don't want to limit user's freedom of using Byte or Integer . Are these number classes interchangeable, ie, can Byte cast to Double in some way?

Thanks!!

EDIT:

I am implementing Dijkstra's algorithm with generics, which calculates the least weighted path. This means the edge labels can be accumulated in some way, and the most general class for this purpose that I can think of is Number .

First of all, your assumption that

Since each Number object should have a double value, when instantiating a new instance of type EI would like to give it a double value.

is not correct.

For example, how can you instantiate a Integer with a double value 1.5? Should it instantiate by rounding? By truncating? I can very well define a subclass of Number that doesn't even support arbitrary integer, like the following one:

public static class Zero extends Number {
    @Override
    public double doubleValue() {
        return 0;
    }

    @Override
    public float floatValue() {
        return 0;
    }

    @Override
    public int intValue() {
        return 0;
    }

    @Override
    public long longValue() {
        return 0;
    }
}

How do you instantiate a Zero with a double value like 1.5?

Since there is no universal logic that can instantiate an arbitrary subclass of Number with an arbitrary double value (this is the reason why Number don't have an constructor with a double argument), the only reasonable way is to ask the client to provide a factory that can fabricate an instance of a subclass of Number given an arbitrary double value with custom logic that applies to that specific subclass. Like the following:

  public class Foo<E extends Number> {

    public static interface NumberFactory<T extends Number> {
        T createByDoubleValue(double value);
    }

    private final NumberFactory<E> factory;

    public Foo(NumberFactory<E> factory) {
        this.factory = factory;
    }

    ...
    public void someMethod() {
      ... // some computation
      // Because every Number has a doubleValue(),
      // I would like to give newInstance a double value, how?
      E instance = factory.createByDoubleValue(1.5);
    }
  }

To use Foo class, the client need to define the factory, like the following:

Foo<Float> foo = new Foo<>(new Foo.NumberFactory<Float>() {
  @Override
    public Float createByDoubleValue(double value) {
      return new Float(value);
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM