【问题标题】:way to initialize a javabean to random values将javabean初始化为随机值的方法
【发布时间】:2009-05-08 07:29:09
【问题描述】:

我正在寻找一些实用程序类/代码,它们将采用 java bean 并将其所有值初始化为随机值。它可以通过反射来完成,因为一些库已经创建了 toString() 或 equals() 方法。在开发 UI 以获取一些数据时很有用。

其他可能的好东西:

  1. 也递归初始化非原始或简单(字符串、日期)成员
  2. 初始化 bean 集合
  3. 也许可以提供一些方法来限制生成的值,例如我们可以给出范围的数字、字符串正则表达式或通配符...

有人知道这样的事情吗? 谢谢

编辑:解决...让 Apocalisp 的示例正常工作,这绝对是我想要的。恕我直言,它有一些缺点:

  • 该库的范围比该用途大得多,但这对我来说不是问题
  • 除非您花一些时间来研究整个事物,否则要了解如何为您的对象构建 Arbitrary 是相当复杂的。这是一个缺点。
  • 我猜它可能更简洁,但这也很好。

谢谢!

【问题讨论】:

    标签: java random javabeans


    【解决方案1】:

    看看Easy Random:https://github.com/j-easy/easy-random

    它允许您使用随机数据填充 Java 对象图。

    免责声明:我是该库的作者

    【讨论】:

      【解决方案2】:

      虽然我确实注意到这篇文章可能有点老了,但我只是碰巧有同样的必要性,而且所提出的解决方案似乎都不能很好地解决它,所以我做了一些快速而肮脏的 15 分钟用于生成随机填充的 bean 的非通用实用程序方法,对于碰巧遇到类似问题的其他人可能有用也可能没有用:

      import java.beans.PropertyDescriptor;
      import java.math.BigDecimal;
      import java.math.RoundingMode;
      import java.util.ArrayList;
      import java.util.Calendar;
      import java.util.Collection;
      import java.util.Date;
      import java.util.Random;
      
      import org.springframework.beans.BeanUtils;
      
      public class RandomBeanUtil {
      
          public static <T> Collection<T> generateTestData(Class<T> clazz, int quantity) {
              Collection<T> list = new ArrayList<T>();
      
              PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz);
              Random rand = new Random();
      
              Calendar cal = Calendar.getInstance();
              cal.set(Calendar.HOUR, 0);
              cal.set(Calendar.MINUTE, 0);
              cal.set(Calendar.SECOND, 0);
              cal.set(Calendar.MILLISECOND, 0);
      
              try {
                  for (int i = 0; i != quantity; i++) {
                          T o = clazz.newInstance();
      
                          for (PropertyDescriptor descriptor : descriptors) {
                              Class<?> type = descriptor.getPropertyType();
                              if (String.class.isAssignableFrom(type)) {
                                  descriptor.getWriteMethod().invoke(o, String.valueOf(new char[]{
                                          (char)('A' + rand.nextInt(26)), (char)('a' + rand.nextInt(26)) }));
                              } else if (Date.class.isAssignableFrom(type)) {
                                  cal.add(Calendar.DATE, rand.nextInt(60) - 30);
                                  descriptor.getWriteMethod().invoke(o, cal.getTime());
                              } else if (BigDecimal.class.isAssignableFrom(type)) {
                                  descriptor.getWriteMethod().invoke(o, 
                                          new BigDecimal(rand.nextDouble() * 500).setScale(2, RoundingMode.HALF_UP));
                              }
                          }
      
                          list.add(o);
                  }       
              } catch (Exception e) {
                  // TODO: Improve exception handling
                  throw new RuntimeException("Error while generating the bean collection", e);
              }
      
              return list;
          }
      
      }
      

      【讨论】:

        【解决方案3】:

        看看Gen class from the Reductio library。这是用于生成或多或少任何类型的arbitrary values 的高度可配置框架的一部分。提供了原始类型和大多数 Java 集合类的生成器。您应该能够相当轻松地为您的类创建Arbitrary 实例。

        编辑这是示例,已更正:

        import static fj.test.Arbitrary.*;
        import static fj.Function.*;
        
        static final Arbitrary<Person> personArbitrary =
          arbitrary(arbInteger.gen.bind(arbString.gen, arbBoolean.gen,
              curry(new F3<Integer, String, Boolean, Person>() {
                public Person f(final Integer age, final String name, final Boolean male)
                  {return new Person(age, name, male);}})));
        

        然后像这样生成一个“大小 100”的任意人。 IE。它的名称最多为 100 个字符。

        Person p = personArbitrary.gen.gen(100, Rand.standard);
        

        【讨论】:

        • 类似的东西正是我想要的,但是调用这个例子的语法有点吓人......该死。让我试试看。
        • 不幸的是,它很冗长,但它是 Java,所以你能做什么。注意“new F>>(){...}”也可以写成“curry(new F3(){。 ..})”。这应该会更短。
        • @raticulin 如果这是答案,您可以这样标记它吗?然后我们都知道它有效!
        • extraneon:我想先测试,然后肯定会
        • 我无法编译它,即使在库源代码中也找不到任何方法 arbInteger() ......并且想知道是否可以通过某种方式使用反射来进一步缩短它。
        【解决方案4】:

        我没有适合你的库,但如果你有一个随机生成器,那么也许这个类可以派上用场:

        public class BeanMethodIterator implements Iterable<Method> {
        
            private static final int MODIFIER_FILTER = (Modifier.PUBLIC | Modifier.STATIC);
            private static final int MODIFIER_EXPECTED = Modifier.PUBLIC;
        
            /**
             * Indicator to filter getter or setter methods. 
             */
            public enum Filter {
        
                /** Only getter methods. */
                GETTERS(new Transform<Method, Boolean>(){
                    public Boolean transform(Method input) {
                        return (input.getName().startsWith("get") || 
                                input.getName().startsWith("is")) 
                            &&  input.getParameterTypes().length == 0;
                    };
                }),
        
                /** Only setter methods. */
                SETTTERS(new Transform<Method, Boolean>(){
                    public Boolean transform(Method input) {
                        return input.getName().startsWith("set") && 
                            input.getParameterTypes().length == 1;
                    };
                }),
        
                /** Getter and setter methods. */
                BOTH(new Transform<Method, Boolean>(){
                    public Boolean transform(Method input) {
                        return Filter.SETTTERS.condition.transform(input) || 
                            Filter.GETTERS.condition.transform(input);
                    };
                });
        
                private Transform<Method, Boolean> condition;
        
                private Filter(Transform<Method, Boolean> condition) {
                    this.condition = condition;
                }
        
            };
        
            /**
             * Iterate parent methods also?
             */
            public enum Scope {
                PARENTS_ALSO() {
                    @Override
                    protected Method[] getMethods(Class<?> c) {
                        return c.getMethods();
                    };
                },
                THIS_CLASS_ONLY() {
                    @Override
                    protected Method[] getMethods(Class<?> c) {
                        return c.getDeclaredMethods();
                    }
                };
        
                protected abstract Method[] getMethods(Class<?> c);
            }
        
            private final Filter filter;
            private final Scope scope;
            private final Class<?> theClass;
        
            /**
             * Constructor. 
             *
             * @param theClass
             * @param what
             */
            public BeanMethodIterator(Class<?> theClass, Filter what, Scope scope) {
                this.filter = what;
                this.theClass = theClass;
                this.scope = scope;
            }
        
            /**
             * Constructor. 
             */
            public BeanMethodIterator(Class<?> theClass) {
                this(theClass, Filter.BOTH, Scope.PARENTS_ALSO);
            }
        
            /**
             * Tells if a method is public
             * @param method
             * @return
             */
            private static boolean isPublic(Method method) {
                return (method.getModifiers() & MODIFIER_FILTER) == MODIFIER_EXPECTED; 
            }
        
            /**
             * {@inheritDoc}
             * @see java.lang.Iterable#iterator()
             */
            public Iterator<Method> iterator() {
                final Method[] methods = this.scope.getMethods(this.theClass);        
        
                return new Iterator<Method>() {
                    int index = 0;
        
                    public boolean hasNext() {
                        while (index < methods.length) {
                            if (isPublic(methods[index]) && filter.condition.transform(methods[index]))
                                return true;
                            index++;
                        }
                        return false;
                    }
        
                    public Method next() {
                        if (!hasNext())
                            throw new NoSuchElementException();
                        return methods[index++];
                    }
        
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
        
                };
            }
        
            public static void main(String[] args) {
                for (Method m: new BeanMethodIterator(Date.class, Filter.GETTERS, Scope.THIS_CLASS_ONLY)) {
                    System.out.println(m.getName());
                }
            }
        
        }
        
        
        /**
         * Represents a function that takes one input and returns a transformation of that input value i.e.
         * a transformation. The name Transform is used because it is shorter.
         * 
         * @author Hannes de Jager
         * @since 01 Sep 2008
         */
        interface Transform<I, O> {
        
            /**
             * Invokes the function, performing the transformation, to produce an interpreted value.
             * 
             * @param input the input value.
             * @return The computed result.
             */
            public O transform(I input);
        }
        

        【讨论】:

        • btw:按如下方式使用:for(Method m: new BeanMethodIterator(bean.getClass(), BeanMethodIterator.Filter.SETTTERS, BeanMethodIterator.Scope.THIS_CLASS_ONLY)) { // 你的代码在这里 }
        • 我不得不承认,在快速查看了您的代码后,我仍然看不清楚它的作用。还没有运行它。所以我会花一些时间来玩它。
        • 我已经更新了代码,我看到里面有一些依赖于外部代码的代码,我已经删除了依赖项。我还添加了一个主要方法来说明该类的使用。
        • 谢谢,一直在看。据我所知,它用于迭代给定类的方法(有一些变体、setter、它自己的等)。但这与我的问题有什么关系?也就是说,为 bean 的成员生成随机值。
        【解决方案5】:

        Apache Commons BeanUtils (http://commons.apache.org/beanutils) 可能对您有用。没有任何实用程序可以开箱即用,但我想所有的构建块都在那里,即访问属性、随机生成器。

        【讨论】:

        • 我已经在使用 commons-beanutils,但我正在寻找更具体的东西。顺便说一句,我使用来自 commons-lang 的 RamdomUtils 等,不知道 beanutils 有随机的东西
        【解决方案6】:

        您可以使用InPUT 开源库做您想做的事情。它使用基于 XML 描述符的范围定义,而不是代码内定义。 InPUT 使用方法和构造函数注入,支持任意初始化深度的复杂对象结构。 ExamplesTutorials 可用。

        【讨论】:

          猜你喜欢
          • 2014-12-11
          • 2011-02-21
          • 1970-01-01
          • 2014-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多