仅将 java 类实例转换为原始类型

Posted

技术标签:

【中文标题】仅将 java 类实例转换为原始类型【英文标题】:Transform java class instance to primitive types only 【发布时间】:2012-07-14 12:33:37 【问题描述】:

我想将一个实例从给定的 Java 类“扁平化”/转换为另一个仅包含原始类型的实例。

还必须递归地展平对象中的每个字段,而不是原始类型,以便生成的对象包含原始对象的展平视图,仅具有基本类型。

例如,给定以下类:

class Element 
  int id_;
  Position position_;


class Position 
  int x_;
  int y_;

结果实例的类型为:

class FlattenedElement 
  int id_;

  int x_;
  int y_;

我会期待这样的行为:

Element e = new Person ( 42, new Position(0, 0) );
FlattenedElement fe = e.flatten();

是否有任何工具/库可以做到这一点?

或者我是否需要使用我采用的反射 API 编写自己的 flattener?

-- 编辑以下大多数 cmets--

我更改了示例以避免与 Stringbyte 混淆(我不必处理字符串)。

我需要在结果转换中保留数据的语义。输出的原始类型数据将直接参与使用 OpenCL 进行的并行计算,OpenCL 只理解原始数据类型。

换句话说,我需要打破封装,直接操作嵌入在类层次结构中的原始数据类型。

【问题讨论】:

有什么理由不将字符串展平为char[] 是的。我想使用一个名为 Aparapi 的库,它只支持原始类型但 char ;) 使用反射编写自己的扁平化器。 应该足够简单来处理反射。但更好的问题是,你为什么会想要这样的东西?我想不出一个有意义的理由。我想我们可以很确定您在这里尝试解决错误的问题。 这是您要求的一项非常专业的任务,不要指望图书馆。您实际上是以一种非常非标准的方式序列化您的对象。也许将所有内容都变成byte[] 会少一些工作——这就是序列化为您所做的。 【参考方案1】:

您可以这样做,但您需要第三方库来创建新类,例如 Javaassist。要内省要展平的类,您将使用反射,正如一些用户已经说过的那样。这是我为你写的另一个例子:

public static Class flatten( Class classToFlatten ) 

    for ( Field f : classToFlatten.getDeclaredFields() ) 

        Class type = f.getType();
        String name = f.getName();
        int modifiersConfig = f.getModifiers();

        // extract all modifiers here (using the isXXX methods of the Modifier class)
        System.out.print( Modifier.isPrivate( modifiersConfig ) ? "private" : "" );
        System.out.print( " " + type );
        System.out.print( " " + name );
        System.out.println();

        if ( type.isPrimitive() ) 
            // primitive type.
            // does not need to be converted.
            // insert in the new class as it is (using Javaassist).
         else 

            // no primitive type.
            // needs to be converted and tested.
            // insert in the new class after the conversion (using Javaassist).

            // convert rules...
            switch ( type.getSimpleName() ) 

                case "String":
                    // insert in the new class a array of chars.
                    break;

                // cases to test if the field is a wrapper (Integer, Long, etc.).

                // other rules tha you need here...

            

            // here you need to use recursion...
            // you can use this method, but you will need to create
            // a new parameter, passing the class that is been built
            // to insert new fields in it (relative to the type that is been
            // reflected)

        
    

    // return the new class here and outside the method, use the newInstance
    // method to create new instances of this class
    return null;


有了这个,我认为你将能够做你需要的,但我想你为什么需要这个。当你有某种类型的数组会被递归地进行扁平化时,你会遇到一些问题,因为你可能需要“回溯”来解析它们的类型或运行扁平化算法。对于泛型、内部类、方法和各种类成员,您将遇到同样的问题。我并不是说这是不可能的,但它会消耗你很多时间,也许你可以像一些用户已经说过的那样以更简单的方式解决你的问题。好吧,我希望你能做你需要的,如果可能的话我想知道结果!也许您的解决方案可以成为新图书馆的种子!好的,集思广益:D 这里有一些链接。

The Javaassist library can be downloaded here.

Here you can see a simple tutorial. 我建议您仅在开始时使用它,因为自创建教程以来 Javaassist API 可能已得到改进,因此,在阅读本文后,重构您的代码(如果可能),阅读库文档。

【讨论】:

【参考方案2】:

嗯,从我的观点来看,一种方法是:

public class Person 
    String name;
    Atring address;

    public FlattenedPerson flatten() 
        FlattenedPerson fp = new FlattenedPerson(this.name.getBytes(), this.houseNumber, this.address.getStreet.getBytes(), this.address.getTown.getBytes());
        return fp;
    

【讨论】:

感谢您的回答,但这不是我所期望的。我需要一种能够适应任何类的动态行为。 啊,您可能想要编辑您的问题,即您正在为任何课程寻找图书馆/方法。 (我假设您想保留原始类型并将其他所有内容都转换为字节数组?)【参考方案3】:

你必须使用反射

查看the little sample,返回字段名称。

因此,要获取此字段的值,您必须返回 f[i].get(Object)

【讨论】:

以上是关于仅将 java 类实例转换为原始类型的主要内容,如果未能解决你的问题,请参考以下文章

Java var定义基本数据类型变量实际类型问题(原始类型或包装类)

java 中的原始类型与原始封装类型

如何从 String 转换为原始类型或标准 java Wrapper 类型

原始类型包装器

在逻辑上表示单个值时将类转换为结构,类似于原始类型

将 Streams 与原始数据类型和相应的包装器一起使用