有時我會看到在方法呼叫中使用菱形運算子的示例。
語法的一個例子是:
.<ClassName>methodName()
我不確定我是否完全理解在哪種情況下可以使用這種情況。在參考文獻中沒有找到對此的解釋。
您能否解釋一下該案例或建議我可以找到解釋的資訊來源?
我在下面提供了一個示例。本示例使用 RxJava2。沒有Flowable.<Integer>create(emitter -> emit(emitter), BackpressureStrategy.BUFFER)
編譯,<Integer>
因為方法 emit 接受FlowableEmitter<Integer> emitter
。
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.schedulers.Schedulers;
public class Sample {
public static void main(String[] args) {
Flowable.<Integer>create(emitter -> emit(emitter), BackpressureStrategy.BUFFER)
.observeOn(Schedulers.computation(), true,2)
.map(data -> data * 1)
.subscribe(Sample::process,
err -> System.out.println("ERROR: " err),
() -> System.out.println("DONE"));
}
public static void process(int value) {
System.out.println(value);
sleep(1000);
}
private static void emit(FlowableEmitter<Integer> emitter) {
int count = 0;
while(count < 10) {
count ;
System.out.println("Emitting ..." count);
emitter.onNext(count);
sleep(500);
}
}
private static boolean sleep(int ms) {
try {
Thread.sleep(ms);
return true;
} catch (InterruptedException e) {
return false;
}
}
}
當我嘗試使用純 Java 模擬類似情況時,它不起作用。我理解錯了什么?
public class Sample2 {
public static void main(String[] args) {
GenericClass.<Integer>genericMethod(param -> processParam(param));
}
private static void processParam(GenericClass<Integer> b) {
}
}
}
class GenericClass <T> {
public static <T> GenericClass<T> genericMethod(GenericInterface<T> genericinterface) {
return new GenericClass<T>();
}
}
interface GenericInterface <T> {
T doJob();
}
uj5u.com熱心網友回復:
ClassName.<Type>methodName(...)
是Java中方法呼叫的一種形式。JLS中列出了許多其他形式:
MethodInvocation:
MethodName ( [ArgumentList] )
TypeName . [TypeArguments] Identifier ( [ArgumentList] ) <--- this is the form in question
ExpressionName . [TypeArguments] Identifier ( [ArgumentList] )
Primary . [TypeArguments] Identifier ( [ArgumentList] )
super . [TypeArguments] Identifier ( [ArgumentList] )
TypeName . super . [TypeArguments] Identifier ( [ArgumentList] )
TypeArguments:
< TypeArgumentList >
TypeArgumentList:
TypeArgument {, TypeArgument}
在 中<...>
,您應該為泛型方法的每個型別引數顯式撰寫型別引數。
請注意,這ClassName<Type>.methodName
不是其中一種形式。
在嘗試用普通 Java 模擬這種行為時,您錯過的主要事情是GenericInterface.doJob
應該帶一個引數,因為您傳入的 lambda 有一個引數:
param -> processParam(param)
^^^^^
這個引數應該是 type GenericClass<T>
,因為這是processParam
需要的。
interface GenericInterface <T> {
void doJob(GenericClass<T> param);
}
這類似于 中的subscribe
方法FlowableOnSubscribe<T>
,它是Flowable.create
作為引數的。
請注意,subscribe
它與回傳的型別不同Flowable.create
,但我們與GenericClass.genericMethod
回傳的型別相同。這仍然模擬了“寫入型別引數顯式編譯但省略它會產生錯誤”的相同行為,因此我不會費心創建新型別。
Flowable.create
現在你得到了與RxJava中的方法相同的行為:
GenericClass.genericMethod(param -> processParam(param)); // error
GenericClass.<Integer>genericMethod(param -> processParam(param)); // OK
這是因為 Java 的型別推斷演算法不夠強大,無法在第一種情況下正確推斷型別。
盡管如此,這和 RxJava 還是有區別的 -Flowable.create
需要 a FlowableOnSubscribe<T>
,它有一個 ``
uj5u.com熱心網友回復:
您可以將示例擴展為:
class Sample2 {
public static void main(String[] args) {
GenericClass.genericMethod(new GenericInterface<Integer>() {
@Override
public Integer doJob(? param) {
return param;
}
}));
}
private static void processParam(GenericClass<Integer> b) {
}
}
}
class GenericClass <T> {
public static <T> GenericClass<T> genericMethod(GenericInterface<T> genericinterface) {
return new GenericClass<T>();
}
}
interface GenericInterface <T> {
T doJob();
}
如您所見,您的 lambda 運算式需要一些輸入引數“?param”,它與 GenericInterface#doJob 的簽名不匹配。如果您將代碼更改為此:
lass Sample2 {
public static void main(String[] args) {
GenericClass.genericMethod(param -> processParam(param)); // <- this compiles now without any "<..>"
}
private static void processParam(GenericClass<Integer> b) {
}
}
}
class GenericClass <T> {
public static <T> GenericClass<T> genericMethod(GenericInterface<T> genericinterface) {
return new GenericClass<T>();
}
}
interface GenericInterface <T> {
T doJob(T param);
}
當您與 lamdas 和功能介面斗爭時,請嘗試將它們擴展到它們的匿名內部類對應物。這可以幫助您的 IDE 讓您的腳步更好,并使此類錯誤更加明顯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/494512.html