如何将泛型 class 类型转换为特定类型?
How to convert a generic class type to a specific type?
我正在尝试使用 Java 8 中的泛型类型创建一个 Flux 泛型转换器。我的代码基于此 answer。这个想法基本上是实现这个特定的转换器 String
-> Integer
:
public Flux<Integer> createFluxConverterStringToInt(String[] data) {
Flux<Integer> stringFlux = Flux
.just(data)
.map(value -> Integer.parseInt(value))
.log();
return stringFlux;
}
到类型转换器 String
-> 到我想要的任何类型。因此,我正在使用构造函数 FluxAndMonoGeneric(Class<OUT> typeArgumentClass)
创建类型 <OUT>
的 class FluxAndMonoGeneric
,并返回方法 public Flux<OUT> createFluxConverter(String[] data)
。我正在考虑像这样创建多个条目:this.typeArgumentClass.isInstance(Integer.class)
在 map
调用上,但具有不同的 class 类型。但它甚至对整数不起作用。
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Slf4j
public class FluxAndMonoGeneric<OUT> {
private final Class<OUT> typeArgumentClass;
public FluxAndMonoGeneric(Class<OUT> typeArgumentClass) {
this.typeArgumentClass = typeArgumentClass;
}
public Flux<OUT> createFluxConverter(String[] data) {
Flux<OUT> stringFlux = Flux
.just(data)
.map(value -> {
// NEVER ENTERS ON THIS IF
if (this.typeArgumentClass.isInstance(Integer.class))
return this.typeArgumentClass.cast(Integer.parseInt(value));
// ALWAYS ENTERS ON THIS ELSE AND STRING CANNOT BE CASTED TO INTEGER
else return this.typeArgumentClass.cast(value);
})
.log();
return stringFlux;
}
public Mono<OUT> createMonoConverter(String data) {
Mono<OUT> integerMono = Mono.just(data)
.map(value -> this.typeArgumentClass.cast(value))
.log();
return integerMono;
}
}
我收到错误:java.lang.ClassCastException: Cannot cast java.lang.String to java.lang.Integer
当我使用此单元测试进行测试时。
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
public class FluxAndMonoGenericTest {
// this works.
@Test
void testCreateGenericFluxWithString() {
String expect = "Spring,Spring Boot,Reactive Spring";
String delimiter = ",";
String[] messages = expect.split(delimiter);
FluxAndMonoGeneric<String> myFluxGenericTest = new FluxAndMonoGeneric<String>(String.class);
Flux<String> stringFlux = myFluxGenericTest.createFluxConverter(messages);
StepVerifier.create(stringFlux)
.expectNext(messages[0])
.expectNext(messages[1])
.expectNext(messages[2])
.verifyComplete();
}
// THIS DOES NOT WORK
@Test
void testCreateGenericFluxWithInteger() {
String expect = "1,1234,7654,34";
String delimiter = ",";
String[] messages = expect.split(delimiter);
Integer[] expectedMessages = new Integer[]{1, 1234, 7654, 34};
FluxAndMonoGeneric<Integer> myFluxGenericTest = new FluxAndMonoGeneric<Integer>(Integer.class);
Flux<Integer> stringFlux = myFluxGenericTest.createFluxConverter(messages);
StepVerifier.create(stringFlux)
.expectNext(expectedMessages[0])
.expectNext(expectedMessages[1])
.expectNext(expectedMessages[2])
.expectNext(expectedMessages[3])
.verifyComplete();
}
}
public <T> Flux<T> createFluxConverterStringToInt(String[] data, Function<String, T> mapper) {
return Flux
.just(data)
.map(mapper)
.log();
}
然后,无需传入所需的输出类型,只需传入要将数据转换为正确输出类型的映射器即可。
例如Integer::parseInt
或 String::trim
或其他。
我正在尝试使用 Java 8 中的泛型类型创建一个 Flux 泛型转换器。我的代码基于此 answer。这个想法基本上是实现这个特定的转换器 String
-> Integer
:
public Flux<Integer> createFluxConverterStringToInt(String[] data) {
Flux<Integer> stringFlux = Flux
.just(data)
.map(value -> Integer.parseInt(value))
.log();
return stringFlux;
}
到类型转换器 String
-> 到我想要的任何类型。因此,我正在使用构造函数 FluxAndMonoGeneric(Class<OUT> typeArgumentClass)
创建类型 <OUT>
的 class FluxAndMonoGeneric
,并返回方法 public Flux<OUT> createFluxConverter(String[] data)
。我正在考虑像这样创建多个条目:this.typeArgumentClass.isInstance(Integer.class)
在 map
调用上,但具有不同的 class 类型。但它甚至对整数不起作用。
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Slf4j
public class FluxAndMonoGeneric<OUT> {
private final Class<OUT> typeArgumentClass;
public FluxAndMonoGeneric(Class<OUT> typeArgumentClass) {
this.typeArgumentClass = typeArgumentClass;
}
public Flux<OUT> createFluxConverter(String[] data) {
Flux<OUT> stringFlux = Flux
.just(data)
.map(value -> {
// NEVER ENTERS ON THIS IF
if (this.typeArgumentClass.isInstance(Integer.class))
return this.typeArgumentClass.cast(Integer.parseInt(value));
// ALWAYS ENTERS ON THIS ELSE AND STRING CANNOT BE CASTED TO INTEGER
else return this.typeArgumentClass.cast(value);
})
.log();
return stringFlux;
}
public Mono<OUT> createMonoConverter(String data) {
Mono<OUT> integerMono = Mono.just(data)
.map(value -> this.typeArgumentClass.cast(value))
.log();
return integerMono;
}
}
我收到错误:java.lang.ClassCastException: Cannot cast java.lang.String to java.lang.Integer
当我使用此单元测试进行测试时。
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
public class FluxAndMonoGenericTest {
// this works.
@Test
void testCreateGenericFluxWithString() {
String expect = "Spring,Spring Boot,Reactive Spring";
String delimiter = ",";
String[] messages = expect.split(delimiter);
FluxAndMonoGeneric<String> myFluxGenericTest = new FluxAndMonoGeneric<String>(String.class);
Flux<String> stringFlux = myFluxGenericTest.createFluxConverter(messages);
StepVerifier.create(stringFlux)
.expectNext(messages[0])
.expectNext(messages[1])
.expectNext(messages[2])
.verifyComplete();
}
// THIS DOES NOT WORK
@Test
void testCreateGenericFluxWithInteger() {
String expect = "1,1234,7654,34";
String delimiter = ",";
String[] messages = expect.split(delimiter);
Integer[] expectedMessages = new Integer[]{1, 1234, 7654, 34};
FluxAndMonoGeneric<Integer> myFluxGenericTest = new FluxAndMonoGeneric<Integer>(Integer.class);
Flux<Integer> stringFlux = myFluxGenericTest.createFluxConverter(messages);
StepVerifier.create(stringFlux)
.expectNext(expectedMessages[0])
.expectNext(expectedMessages[1])
.expectNext(expectedMessages[2])
.expectNext(expectedMessages[3])
.verifyComplete();
}
}
public <T> Flux<T> createFluxConverterStringToInt(String[] data, Function<String, T> mapper) {
return Flux
.just(data)
.map(mapper)
.log();
}
然后,无需传入所需的输出类型,只需传入要将数据转换为正确输出类型的映射器即可。
例如Integer::parseInt
或 String::trim
或其他。