在重构代码的过程中,我遇到了或多或少的情况;为了这个例子,在这里重写:
public class UrlProbe {
private final OkHttpClient http;
private final String url;
private final Function<Response, Object> transform;
private Object cachedValue;
public UrlProbe(OkHttpClient http, String url) {
this(http, url, this::debuggingStringTransform);
}
public UrlProbe(OkHttpClient http, String url, Function<Response, Object> transform) {
this.http = http;
this.url = url;
this.transform = transform;
}
private Object debuggingStringTransform(Response response) {
String newValue = response.body().toString();
System.out.println("Debugging new value from url " + url + ": " + newValue);
return newValue;
}
public synchronized Object probe() {
if (cachedValue != null) {
return cachedValue;
}
try (Response response = http.newCall(new Request.Builder().url(url).get().build()).execute()) {
cachedValue = transform.apply(response);
return cachedValue;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
此代码无法编译,因为我们cannot reference this before supertype constructor has been called
:
public UrlProbe(OkHttpClient http, String url) {
this(http, url, this::debuggingStringTransform);
}
以下内容不会编译:
public UrlProbe(OkHttpClient http, String url) {
this(http, url, response -> debuggingStringTransform(response));
}
我发现的唯一方法是明确使用非链接构造函数:
public UrlProbe(OkHttpClient http, String url) {
this.http = http;
this.url = url;
this.transform = this::debuggingStringTransform;
}
虽然限制在构造函数中使用this
链接参数是有意义的,但我发现在这个特定的上下文中它令人惊讶,因为似乎没有对由于在涉及方法引用和lambda表达式的内容时使用this
。
这种限制背后是否存在理由,因为JLS§8.8.7.1是这样说的?
答案 0 :(得分:2)
允许引用此范围尽早破坏看起来像这样的代码
public class UrlProbe {
final String url;
final String param2;
public UrlProbe(String url) {
this(url, this::debuggingStringTransform);
}
public UrlProbe(String url, Function<String, String> transform) {
this(url, transform.apply("")); // <-- What should happen when url is referenced here?
}
public UrlProbe(String url, String param2) {
this.url = url;
this.param2 = param2;
}
private String debuggingStringTransform(String response) {
System.out.println("Debugging new value from url " + url + ": " + response);
return response;
}
}
这至少是违反规则的一种方式。
答案 1 :(得分:1)
IntelliJ在工具提示中显示了为什么这段代码是&#34;坏&#34;:
无法参考&#39;这个&#39;在调用超类型构造函数之前
这是有道理的。您正在构建对象的过程中,定义的方法引用仅在实例化类之后存在。 #39; s&#34;准备好&#34;。
如果您想解决这个问题,可以将该功能更改为静态功能,因为它没有所需的状态:
public UrlProbe(OkHttpClient http, String url) {
this(http, url, UrlProbe::debuggingStringTransform);
}
private static Object debuggingStringTransform(Response response) {
String newValue = response.body().toString();
System.out.println("Debugging new value from url " + url + ": " + newValue);
return newValue;
}
...虽然不可否认看到奇怪的看到private static
方法。
或者,在同一个包中存在别处这个函数,就像在这个函数底部的静态类中一样:
public UrlProbe(OkHttpClient http, String url) {
this(http, url, Functions::debuggingStringTransform);
}
static class Functions {
static Object debuggingStringTransform(Response response) {
String newValue = response.body().toString();
System.out.println("Debugging new value from url " + url + ": " + newValue);
return newValue;
}
}