Java中的动态转换

Java中的动态转换,java,Java,我有两个并行类层次结构,我想将对象从一个转换到另一个。我可以通过手动指定转换要做什么来完成,但是我需要指定转换两次:第一次是在实际转换发生时,第二次是在需要调用它时。有没有办法只指定一次 这是一个很好的例子,但我想简化一下。有两个转换函数允许我在输入类(bI,cI)和输出类(bO,cO)之间进行转换。这是不可避免的。不过,这种比较的情形让我很烦恼。是否有一个优雅的解决方案来避免它们 public class ConversionTest { static public class aI

我有两个并行类层次结构,我想将对象从一个转换到另一个。我可以通过手动指定转换要做什么来完成,但是我需要指定转换两次:第一次是在实际转换发生时,第二次是在需要调用它时。有没有办法只指定一次

这是一个很好的例子,但我想简化一下。有两个转换函数允许我在输入类(bI,cI)和输出类(bO,cO)之间进行转换。这是不可避免的。不过,这种比较的情形让我很烦恼。是否有一个优雅的解决方案来避免它们

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);
        }
}