Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java records Generics : non-static type variable T cannot be referenced from a static context

Tags:

java

 public record Result<T>() {
    private static ResultState state;
    private static Exception exception;
    private static T value;

    public Result(T value) {
        state = ResultState.Success;
        value = value;
        exception = null;
    }

    public Result(Exception e) {
        state = ResultState.Faulted;
        exception = e;
        value = null;
    }

    public static Supplier<Boolean> isFaulted = () -> state == ResultState.Faulted;

    public static Supplier<Boolean> isSuccess = () -> state == ResultState.Success;

    public void match(Consumer<T> succ, Consumer<Exception> fail) {
        if (isFaulted.get())
            fail.accept(exception);
        else
            succ.accept(value);
    }
}

Exception

error: non-static type variable T cannot be referenced from a static context
    private static T value;
               ^
like image 866
San Jaisy Avatar asked Sep 11 '26 19:09

San Jaisy


1 Answers

Since T is a generic type that can differ from one instance to another, you cannot use it for a static field. It doesn't have to do with records, it's just how java works. For instance, if you write this class, you'll get the same complication error:

class MyClass<T> {
    public static T staticField; // ... cannot be referenced from a static context
}

As a result, if you replace the generic type T with Object, your code example will work:

static record Result<T>() {
    private static ResultState state;
    private static Exception exception;
    private static Object value;
   
    // ...
}

However, this looks wrong because each computation will override the previous (static) result. In my opinion, the correct way would be declare the state, value and exception fields inside the record itself, like this:

static record Result<T>(
    ResultState state,
    T value,
    Exception exception
) {

    public Result(T value) {
        this(ResultState.Success, value, null);
    }

    public Result(Exception e) {
        this(ResultState.Success, null, e);
    }

    public void match(Consumer<T> succ, Consumer<Exception> fail) {
        if (state == ResultState.Faulted)
            fail.accept(exception);
        else
            succ.accept(value);
    }
}
like image 88
Emanuel Trandafir Avatar answered Sep 13 '26 07:09

Emanuel Trandafir