Ivan Gerasimenko
Ivan Gerasimenko

Reputation: 2428

Add null-like value to String in Java

I am writing test method like setTask(Task task). And Task object has several fields, e.g.

public String vehicle;

Method setTask should be used in different test-cases, so I'd like to have an options for this field to accept values:

So what can I do to make String to be SpecialString which could accept values null, random & some string value? (BTW: I don't want to set it to string value "RANDOM", and chech whether the value is equal to "RANDOM"-string)

UPDATE: I don't mean random like random value from a set of values, I mean random as well as null and this is for setTask() to handle random (select random from drop-down), and not to pass a random string from a set of values.

Pseudocode:

Task task = new Task();
task.vehicle = random;   // as well as null

setTask(task)

in setTask(Task task):

if (task.vehicle == null) {
    //skip
} else if (task.vehicle == random) {
    // get possible values from drop-down list
    // select one of them
} else {
    // select value from drop-down list which is equal to task.vehicle
}

Upvotes: 0

Views: 379

Answers (2)

BambooleanLogic
BambooleanLogic

Reputation: 8161

What you may want to do is to create an object that wraps a string as well as some information about whether or not it's a special value. Something along the lines of...

public class Special<T> {
    public enum Type {
        NOTHING, RANDOM, SPECIFIC
    }

    private final Type type;
    private final T specificValue;

    public Special(Type type, T specificValue) {
        this.type = type;
        this.specificValue = specificValue;
    }

    public Type getType() {
        return type;
    }

    public T getSpecificValue() {
        if (type != SPECIFIC) {
            throw new IllegalStateException("Value is not specific");
        }
        return specificValue;
    }
}

The class above could be used like so:

Special<String> a = new Special<>(Special.Type.NOTHING, null);
Special<String> b = new Special<>(Special.Type.SPECIFIC, "Hello");

if (b.getType() == Special.Type.RANDOM) {
    // do something
}else if (b.getType() == Special.Type.SPECIFIC) {
    String val = b.getSpecificValue();
    // do something else
}

A slightly more polished variant of the thing above is probably the best way, but there is a way, a much uglier way, to do it using nothing but a String field.

What you could do is to have a "magical" string instance that behaves differently from all other string instances, despite having the same value. This would be done by having something like

static final String SPECIAL_VALUE_RANDOM = new String("random");

Note the use of the String constructor, which ensures that the string becomes a unique, non-interned instance. You can then say if (vehicle == SPECIAL_VALUE_RANDOM) { ... } (note the use of == instead of .equals()) to check if that specific instance (rather than any other string that says "random") was used.

Again, this is not a particularly good way of doing this, especially if you intend to do this more than once ever. I would strongly suggest something closer to the first way.

Upvotes: 1

daniu
daniu

Reputation: 14999

Don't assign a fixed String but use a Supplier<String> which can generate a String dynamically:

public Supplier<String> vehicleSupplier;

This, you can assign a generator function as you request:

static Supplier<String> nullSupplier () { return () -> null; }
static Supplier<String> fixedValueSupplier (String value) { return () -> value; }
static Supplier<String> randomSupplier (String... values) {
    int index = ThreadLocalRandom.current().nextInt(values.length) -1;
    return index > 0 && index < values.length ? values[index] : null;
}

In use, this looks like:

task.setVehicleSupplier(nullSupplier()); // or
task.setVehicleSupplier(fixedValueSupplier("value")); // or
task.setVehicleSupplier(randomSupplier("", "Hello, World!", "Iso Isetta"));

and you can get the String by

String value = task.vehicleSupplier().get();

or hide the implementation in a getter function

class Task {
    // ...
    private Supplier<String> vehicleSupplier;
    public void setVehicleSupplier(Supplier<String> s) { 
        vehicleSupplier = s; 
    }
    public String getVehicle() {
        return vehicleSupplier != null ? vehicleSupplier.get() : null;
    }
    // ...
}

Upvotes: 6

Related Questions