英文:
Java records Generics : non-static type variable T cannot be referenced from a static context
问题
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;
^
英文:
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;
^
答案1
得分: 2
因为 `T` 是一个可以在不同实例之间不同的通用类型,你不能将其用于静态字段。这与记录无关,这只是 Java 的工作方式。例如,如果你编写这个类,你将会得到相同的编译错误:
```java
class MyClass<T> {
public static T staticField; // ... 无法从静态上下文引用
}
因此,如果你用 Object
替换通用类型 T
,你的代码示例将会工作:
static record Result<T>() {
private static ResultState state;
private static Exception exception;
private static Object value;
// ...
}
然而,这看起来是错误的,因为每次计算都会覆盖之前的(静态)结果。在我看来,正确的方式应该是在记录本身内部声明 state, value 和 exception 字段,就像这样:
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);
}
}
英文:
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);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论