我已将代码简化为:
static private String waitForString(String expected, int attempts) {
String actual = null;
for (int i = 0; i < attempts; i++){
actual = getString();
if (validateString(actual, expected)) {
return actual;
}
}
return null;
}
static private int waitForInt(int expected, int attempts) {
int actual = 0;
for (int i = 0; i < attempts; i++){
actual = getInt();
if (validateInt(actual, expected)) {
return actual;
}
}
return 0;
}
由于我使用相同的循环(并且由于我有多个具有多个相应的&#34; getter&#34;方法和验证方法的类),我想重构它。我试过这个:
static <T> T helperMethod(Method getMethod, Method validator,T expected, int attempts) {
T actual = null;
for (int i = 0; i < attempts; i++){
actual = method.invoke(null);
if (validator.invoke(null, actual, expected)) {
return actual;
}
}
return null;
}
但是我遇到了以下错误:
actual = method.invoke(null);
error: incompatible types: Object cannot be converted to T
validator.invoke(null, actual, expected)
error: incompatible types: Object cannot be converted to boolean
我可以在函数声明中指定只接受具有正确返回类型的方法吗?如果是这样,怎么样? 其他重构方法的想法将不胜感激。
EDITED 为了说清楚,我没有问如何反映方法的返回类型。 谢谢VGR的解决方案。
答案 0 :(得分:2)
不要使用反射。
对于开发人员(包括您自己)而言,反射速度较慢,难以遵循,并且编译器无法检查正确的参数和返回类型。
在Java中完成等效“指向方法的指针”的正确方法是将各种方法调用包装在一个公共接口中。从Java 8开始,正如Markus Benko指出的那样,你应该使用供应商和谓词:
static <T> T waitForValue(Supplier<T> getMethod, BiPredicate<T, T> validator, T expected, int attempts) {
T actual = null;
for (int i = 0; i < attempts; i++){
actual = getMethod.get();
if (validator.test(actual, expected)) {
return actual;
}
}
return null;
}
private static String waitForString(String expected, int attempts) {
return waitForValue(ThisClass::getString, ThisClass::validateString, expected, attempts);
}
private static int waitForInt(int expected, int attempts) {
return waitForValue(ThisClass::getInt, ThisClass::validateInt, expected, attempts);
}
如果你使用的是旧版本的Java,你可以做更多相同的工作:
private interface Getter<T> {
T get();
}
private interface Validator<T> {
boolean test(T actual, T expected);
}
static <T> T waitForValue(Getter<T> getMethod, Validator<T> validator, T expected, int attempts) {
T actual = null;
for (int i = 0; i < attempts; i++){
actual = getMethod.get();
if (validator.test(actual, expected)) {
return actual;
}
}
return null;
}
private static String waitForString(String expected, int attempts) {
Getter<String> getter = new Getter<String>() {
@Override
public String get() {
return getString();
}
};
Validator<String> validator = new Validator<String>() {
@Override
public boolean test(String actual, String expected) {
return validateString(actual, expected);
}
};
return waitForValue(getter, validator, expected, attempts);
}
private static int waitForInt(int expected, int attempts) {
Getter<Integer> getter = new Getter<Integer>() {
@Override
public Integer get() {
return getInt();
}
};
Validator<Integer> validator = new Validator<Integer>() {
@Override
public boolean test(Integer actual, Integer expected) {
return validateInt(actual, expected);
}
};
return waitForValue(getter, validator, expected, attempts);
}
答案 1 :(得分:1)
出于不同的原因避免使用反射:JVM优化松散,代码编译但在运行时爆炸,代码很难调试。
您可以尝试创建一个接口,其中包含您需要验证的每种类型的实现。
类似的东西:
<强>接口强>
public interface InputHandler<T> {
Boolean wait(T expected);
}
<强>实现:强>
输入字符串的处理程序实现:
public class StringHandler implements InputHandler<String> {
@Override
public Boolean wait(String expected) {
String actual = getString();
return validateString(actual, expected);
}
private String getString() {
// ...
return null;
}
private boolean validateString(String actual, String expected) {
// ...
return false;
}
}
输入Integer的处理程序实现:
public class IntegerHandler implements InputHandler<Integer> {
@Override
public Boolean wait(Integer expected) {
Integer actual = getInt();
return validateInt(actual, expected);
}
private boolean validateInt(Integer actual, Integer expected) {
// ...
return false;
}
private Integer getInt() {
// ...
return null;
}
}
您可以添加和删除所有&#34;处理程序&#34;你需要非常快。
运行示例的应用
public class Test {
public static void main(String[] args) {
waitForValidInput(new StringHandler(), "a", 3);
waitForValidInput(new IntegerHandler(), 5, 3);
}
static private <T> T waitForValidInput(InputHandler<T> validator, T expected, int attempts) {
for (int i = 0; i < attempts; i++) {
if(validator.wait(expected)) {
return expected;
}
}
return null;
}
}
答案 2 :(得分:0)
试试这个:
static <T> T helperMethod(Method method, Method validator, T expected, int attempts) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
T actual = null;
for (int i = 0; i < attempts; i++) {
actual = (T)method.invoke(null);
if ((Boolean)validator.invoke(null, actual, expected)) {
return actual;
}
}
return null;
}
(还在签名中添加了例外,并在参数中将getMehod
更改为method