Java中的动态转换
我有两个并行类层次结构,我想将对象从一个转换到另一个。我可以通过手动指定转换要做什么来完成,但是我需要指定转换两次:第一次是在实际转换发生时,第二次是在需要调用它时。有没有办法只指定一次 这是一个很好的例子,但我想简化一下。有两个转换函数允许我在输入类(bI,cI)和输出类(bO,cO)之间进行转换。这是不可避免的。不过,这种比较的情形让我很烦恼。是否有一个优雅的解决方案来避免它们Java中的动态转换,java,Java,我有两个并行类层次结构,我想将对象从一个转换到另一个。我可以通过手动指定转换要做什么来完成,但是我需要指定转换两次:第一次是在实际转换发生时,第二次是在需要调用它时。有没有办法只指定一次 这是一个很好的例子,但我想简化一下。有两个转换函数允许我在输入类(bI,cI)和输出类(bO,cO)之间进行转换。这是不可避免的。不过,这种比较的情形让我很烦恼。是否有一个优雅的解决方案来避免它们 public class ConversionTest { static public class aI
public class ConversionTest {
static public class aI {}
static public class bI extends aI {}
static public class cI extends aI {}
static public class aO {}
static public class bO extends aO {}
static public class cO extends aO {}
// Convert from bI to bO.
private static aO convert(bI iVar) {return new bO();}
// Convert from cI to cO.
private static aO convert(cI iVar) {return new cO();}
public static void main(String argv []) {
// Input variable.
final aI iVar = new bI();
// Output variable.
final aO temp;
// Perform conversion.
if(iVar instanceof bI) {
temp = convert((bI)iVar);
} else if (iVar instanceof cI) {
temp = convert((cI)iVar);
}
}
}
我想这样做:
final a0 temp = convert(iVar.getClass().cast(iVar));
但在这种情况下,编译器抱怨它找不到合适的转换函数。也许我可以指定一个包含所有可能转换的数组来尝试
final a0 temp = convertHelp({bI,cI}, iVar);
我不知道该如何实现这个convertHelp
功能。它将遍历数组并尝试找到合适的强制转换。有什么建议吗
谢谢。您已经拥有的实现是正确的,并且比使用反射API得到的要漂亮得多 您可以实现
转换帮助
;它需要将Class
对象数组作为参数。但是,同样地,ConvertHelp
的主体将非常丑陋
您所做的与静态类型语言的理想背道而驰。Java并不是为了让它变得简单而设计的——这样很容易产生不安全的代码。您有权访问类实现本身吗?如果将多态性粘贴到每个类中,则可以使用多态性使转换执行正确的操作
class ai
{
public ao convert()
{
return new ao();
}
}
class bi extends ai
{
@Override
public ao convert()
{
return new bo();
}
}
class ci extends ai
{
@Override
public ao convert()
{
return new co();
}
}
public static void main(String argv []) {
// Input variable.
final aI iVar = new bI();
// Output variable.
final aO temp = iVar.convert();
}
专用静态aO转换(aI iVar){
if(bI的iVar实例)
返回新的bO();
if(cI的iVar实例)
返回新的cO();
返回新aO();
}
如果您不希望输入类依赖于输出类,您仍然可以从多态性中获益:
interface IFactory<T> {
public T createA();
public T createB();
public T createC();
}
class ai
{
public T convert(IFactory<T> f)
{
return f.createA();
}
}
class bi extends ai
{
@Override
public T convert(IFactory<T> f)
{
return f.createB();
}
}
class ci extends ai
{
@Override
public T convert(IFactory<T> f)
{
return f.createB();
}
}
class FactoryO extends IFactory<ao> {
public ao createA() {
return new ao();
}
public bo createB() {
return new bo();
}
public co createC() {
return new co();
}
}
鉴于您不能修改输入/输出类,最干净的解决方案可能是使用反射:
class Converter {
public ao convert(ai iObj) {
final Method m = getClass().getDeclaredMethod("cvrt", iObj.getClass());
return (ao)m.invoke(this, iObj);
}
public ao cvrt(ai iObj) {
return new ao();
}
public bo cvrt(bi iObj) {
return new bo();
}
public co cvrt(ci iObj) {
return new co();
}
}
理想情况下,正如其他海报所建议的,您应该在输入类上有一个convert方法,以便它们能够自己生成输出类。如果您想拥有一个并行的转换器层次结构,最好的方法是使用访问者模式 您可以定义ConvertServiceSitor接口,并有以下两种实现:
static public interface ConverterVisitor {
public aO convert(aI iVar);
}
static public class bIConverter implements ConverterVisitor{
public aO convert(aI iVar){
// requires a cast from aI to bI
return new bO();
}
}
static public class cIConverter implements ConverterVisitor{
public aO convert(aI iVar){
// requires a cast from aI to cI
return new cO();
}
}
但是bI和cI类也需要可修改,这不是您想要做的
因此,剩下的唯一解决方案是使用ReflectionVisitor模式
这将涉及编写一个类,该类将使用某种命名约定获取相应的转换器。在这种情况下,转换器的名称是使用在类名后面附加“converter”的约定获得的。因此,转换器工厂实现可能如下所示:
static public class ConverterFactory {
public aO convert(aI ai) throws Exception {
return (aO) ((ConverterVisitor) Class.forName(ai.getClass().getName() + "Converter").newInstance()).convert(ai);
}
}
非常难看!但它是有效的
第二种选择是在工厂中使用某种注册表。
这是完整的清单。这更好,因为它使用泛型来避免多次强制转换
import java.util.HashMap;
import java.util.Map;
public class Trial {
static public class aI {}
static public class bI extends aI {}
static public class cI extends aI {}
static public class aO {}
static public class bO extends aO {}
static public class cO extends aO {}
static public interface ConverterVisitor<T extends aI> {
public aO convert(T iVar);
}
static public class bIConverter implements ConverterVisitor<bI>{
public bIConverter(ConverterFactory converterFactory){
converterFactory.register(bI.class, this);
}
public aO convert(bI iVar){
return new bO();
}
}
static public class cIConverter implements ConverterVisitor<cI>{
public cIConverter(ConverterFactory converterFactory){
converterFactory.register(cI.class, this);
}
public aO convert(cI iVar){
return new cO();
}
}
static public class ConverterFactory {
public Map<Class<?>,ConverterVisitor<?>>converterRegistry = new HashMap<Class<?>, ConverterVisitor<?>>();
public <T extends aI> void register(Class<T> clazz,ConverterVisitor<T> converter){
converterRegistry.put(clazz,converter);
}
@SuppressWarnings("unchecked")
public<T extends aI> aO convert(T ai) {
return ((ConverterVisitor<T>)converterRegistry.get(ai.getClass())).convert(ai);
}
}
public static void main(String argv []) throws Exception {
// Input variable.
final aI iVar = new bI();
// Output variable.
aO temp = null;
// the three lines below must be done in some generic place within the program.
ConverterFactory factory = new ConverterFactory();
new bIConverter(factory);
new cIConverter(factory);
temp = factory.convert(iVar);
System.out.println(temp);
}
}
import java.util.HashMap;
导入java.util.Map;
公开庭审{
静态公共类aI{}
静态公共类bI扩展aI{}
静态公共类cI扩展aI{}
静态公共类aO{}
静态公共类bO扩展aO{}
静态公共类cO扩展aO{}
静态公共接口转换器{
公共aO转换(iVar);
}
静态公共类双转换器实现ConvertServiceSitor{
公共双转换器(转换器工厂转换器工厂){
register(bI.class,this);
}
公共aO转换(bI iVar){
返回新的bO();
}
}
静态公共类cIConverter实现ConvertServiceSitor{
公共转换器(转换器工厂转换器工厂){
register(cI.class,this);
}
公共aO转换(cI iVar){
返回新的cO();
}
}
静态公共类转换器工厂{
publicmap>converterRegistry=newhashmap>();
公共无效寄存器(clazz类、ConverterVisitor转换器){
converterRegistry.put(clazz,converter);
}
@抑制警告(“未选中”)
公共aO转换(T ai){
return((ConverterVisitor)converterRegistry.get(ai.getClass()).convert(ai);
}
}
公共静态void main(字符串argv[])引发异常{
//输入变量。
最终aI iVar=新bI();
//输出变量。
aO温度=零;
//以下三行必须在程序中的某个通用位置完成。
ConverterFactory工厂=新建ConverterFactory();
新型双变流器(工厂);
新变频器(工厂);
温度=工厂转换(iVar);
系统输出打印项次(温度);
}
}
完全正确。请注意(由于Java 5),您可以在重写时使用协变返回类型(即@Override public co convert(){return new co();}
)。我尝试使用类对象,但无法使其工作。我只是不知道类列表的输入类型应该是什么。也许我需要使用原始类,而不是泛型。我故意不想让输入和输出类相互了解。我同意所有人的观点,即使用多态性可以达到目的,但我正在寻找一种替代解决方案。在我的情况下,我无法控制输入/输出类,也无法扩展它们。:)我试图避免instanceof,因为我有很多类。这与什么有关系?我在寻找可以为我提供更好类型安全性的东西,但如果我更喜欢这个解决方案,请
static public class ConverterFactory {
public aO convert(aI ai) throws Exception {
return (aO) ((ConverterVisitor) Class.forName(ai.getClass().getName() + "Converter").newInstance()).convert(ai);
}
}
import java.util.HashMap;
import java.util.Map;
public class Trial {
static public class aI {}
static public class bI extends aI {}
static public class cI extends aI {}
static public class aO {}
static public class bO extends aO {}
static public class cO extends aO {}
static public interface ConverterVisitor<T extends aI> {
public aO convert(T iVar);
}
static public class bIConverter implements ConverterVisitor<bI>{
public bIConverter(ConverterFactory converterFactory){
converterFactory.register(bI.class, this);
}
public aO convert(bI iVar){
return new bO();
}
}
static public class cIConverter implements ConverterVisitor<cI>{
public cIConverter(ConverterFactory converterFactory){
converterFactory.register(cI.class, this);
}
public aO convert(cI iVar){
return new cO();
}
}
static public class ConverterFactory {
public Map<Class<?>,ConverterVisitor<?>>converterRegistry = new HashMap<Class<?>, ConverterVisitor<?>>();
public <T extends aI> void register(Class<T> clazz,ConverterVisitor<T> converter){
converterRegistry.put(clazz,converter);
}
@SuppressWarnings("unchecked")
public<T extends aI> aO convert(T ai) {
return ((ConverterVisitor<T>)converterRegistry.get(ai.getClass())).convert(ai);
}
}
public static void main(String argv []) throws Exception {
// Input variable.
final aI iVar = new bI();
// Output variable.
aO temp = null;
// the three lines below must be done in some generic place within the program.
ConverterFactory factory = new ConverterFactory();
new bIConverter(factory);
new cIConverter(factory);
temp = factory.convert(iVar);
System.out.println(temp);
}
}