我有一个第三方RPC-API,提供类似于java.sql.ResultSet
(用于读取值)和java.sql.PreparedStatement
(用于写入值)的接口。假设它看起来像这样:
public interface RemoteDeviceProxy {
public void setBoolean(Boolean value);
public void setInteger(Integer value);
// ...
public Boolean getBoolean();
public Integer getInteger();
// ...
}
我想为这个API编写一个包装器,它使用泛型来创建特定类型的实例:
public class <T> RemoteVariable {
private final RemoteDeviceProxy wrappedDevice;
public RemoteVariable(RemoteDeviceProxy wrappedDevice) {
this.wrappedDevice = wrappedDevice;
}
public T get() {
// should call wrappedDevice.getBoolean() if T is Boolean, etc.
// how to implement?
}
public void set(T newValue) {
// should call wrappedDevice.setBoolean(newValue) if T is Boolean, etc.
// implement using instanceof
}
}
如何在通用包装器中实现getter?我发现this answer深入解释了类似的情况,但我无法将其转移到我的问题中。具体来说,当我写这篇文章时:
public T get() {
Type[] actualTypeArguments = ((ParameterizedType) getClass())
.getActualTypeArguments();
}
我收到编译错误,说我无法转发ParameterizedType
,我不明白为什么。任何人都可以解释如何实现这个目标吗?
答案 0 :(得分:2)
这是一种方式:
public class <T> RemoteVariable {
private final RemoteDeviceProxy wrappedDevice;
private final Class<T> clazz;
public RemoteVariable(RemoteDeviceProxy wrappedDevice, Class<T> clazz) {
this.wrappedDevice = wrappedDevice;
this.clazz = clazz;
}
public T get() {
if(clazz == Boolean.class){return clazz.cast(wrappedDevice.getBoolean());}
else if(clazz == Integer.class){return clazz.cast(wrappedDevice.getInteger());}
// ...
}
// ...
}
答案 1 :(得分:2)
我想了很长一段时间,最后想出了一个不同的方法:
首先我向你添加了一个getter RemoteVariable
类:
protected RemoteDeviceProxy getWrappedProxy() {
return wrappedProxy;
}
其次,我创建了一个将在以后由工厂使用的构建器界面:
public interface RemoteVariableBuilder {
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy);
}
然后我为Boolean
...
public class RemoteBooleanVariable extends RemoteVariable<Boolean> implements RemoteVariableBuilder {
public RemoteBooleanVariable(RemoteDeviceProxy wrappedProxy) {
super(wrappedProxy);
}
@SuppressWarnings("unchecked")
@Override
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) {
return (RemoteVariable<T>) new RemoteBooleanVariable(wrappedProxy);
}
@Override
public Boolean get() {
return getWrappedProxy().getBoolean();
}
@Override
public void set(Boolean value) {
getWrappedProxy().setBoolean(value);
}
}
......和整数......
public class RemoteIntegerBuilder extends RemoteVariable<Integer> implements RemoteVariableBuilder {
public RemoteIntegerBuilder(RemoteDeviceProxy wrappedProxy) {
super(wrappedProxy);
}
@SuppressWarnings("unchecked")
@Override
public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) {
return (RemoteVariable<T>) new RemoteIntegerBuilder(wrappedProxy);
}
@Override
public Integer get() {
return getWrappedProxy().getInteger();
}
@Override
public void set(Integer value) {
getWrappedProxy().setInteger(value);
}
}
实际上,eclipse在知道基类和接口后创建了大部分代码。
最后一步是创建一个工厂
public class RemoteVariableFactory {
private static final Map<String, RemoteVariableBuilder> BUILDERS = new HashMap<>();
static {
BUILDERS.put(Boolean.class.getName(), new RemoteBooleanVariable(null));
BUILDERS.put(Integer.class.getName(), new RemoteIntegerBuilder(null));
// add more builders here
}
public static <T> RemoteVariable<T> getRemoteVariable(RemoteDeviceProxy wrappedProxy, Class<T> typeClass) {
RemoteVariableBuilder remoteVariableBuilder = BUILDERS.get(typeClass.getName());
if (remoteVariableBuilder == null) {
return null; // or throw an exception whichever is better in your case
}
return remoteVariableBuilder.buildNewVariable(wrappedProxy);
}
}
现在我们准备创建新的RemoteVariables ......
RemoteVariable<Boolean> var1 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Boolean.class);
RemoteVariable<Integer> var2 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Integer.class);
总结一下,让我们快速比较一下Eng.Fouad的答案:
缺点:
优势: