有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在运行时创建Java语句

是否可以在运行时创建和执行java语句

声明如下:

Query q = new Query("type").setFilter(filter1).setFilter(filter2).setFilter(filter3).setFilter(filterN);

我想解决的问题是,这里的查询对象是不可变的,我想在运行时基于给定的一组参数或参数来构建它

将其封装在如下方法中:

Query query = buildQueryFromArgs(type, filterList); 

buildQueryFromArgs方法实质上是在顶部创建java语句

不能这样做:

for(Filter filter : filters){
 query = query.setFilter(filter); 
}

因为这里将发生的是,最后一个过滤器将是唯一应用的过滤器。除非我们这么做query.setFilter(f1).setFilter(f2).setFilter(andSoOn);


共 (2) 个答案

  1. # 1 楼答案

    你有两个选择:

    解决方案#1 像你说的那样创建一个方法。这将被视为一种静态工厂方法。虽然类似于构造函数,但它允许您指定标识符(名称)。尽管如此,如果名称不是问题,静态工厂方法可能会使事情变得过于复杂;只需将列表传递并键入构造函数即可。下面是一个静态工厂方法的示例;使用构造函数需要构造函数是非私有的:

    class Query {
        private List<Filter> filters;
        private String type;
    
        private Query(String type, List<Filter> filters) {
    
        }
    
        public static Query buildWithFilters(String type, List<Filter> filters) {
            return new Query(type, filters);
        }
    }
    

    然后你会这样称呼它:

    List<Filter> filters = new ArrayList<>();
    //add filters
    
    Query query = Query.buildWithFilters("type", filters);
    

    解决方案#2 Builder pattern允许您在构建对象之前设置对象的可选和强制状态。构建后,对象可以保持不变

    class Query {
        private final String type;
        private final List<Filter> filters;
    
        private Query(Builder b) {
            type = b.type;
            type = b.filters;
        }
    
        private static final class Builder {
            private String type;
            private List<Filter> filters;
    
            public Builder(String type) {
                this.type = type;
            }
    
            public Builder addFilter(Filter filter) {
                if(filters == null)
                    filters = new ArrayList<>();
    
                filters.add(filter);
            }
    
            public Query build() {
                return new Query(this);
             }
         }
     }
    

    然后,可以像这样构造对象:

    Query query = new Query.Builder("type").addFilter(filter1).build();
    

    这里的诀窍是将状态存储在Builder实例中,然后将其传递给您试图创建的实例。这允许您在创建对象之前首先指定属性,然后通过builder'abuild()方法使用这些属性构造对象


    如果无法修改Query类,那么下一个选项将是创建一个不可变的包装器:

    final class QueryWrapper {
        private final Query query;
        private final List<Filter> filters;
    
        private QueryWrapper(Builder b) {
            query = b.query;
            filters = b.filters;
        }
    
        public static final class Builder {
            private Query query;
            private List<Filter> filters;
    
            public Builder(Query query) {
                this.query = query;
            }
    
            public Builder addFilter(Filter filter) {
                if(filters == null)
                    filters = new ArrayList<>();
    
                filters.add(filter);
            }
    
            public QueryWrapper build() {
                new QueryWrapper(this);
            }
        }
    }
    

    包装器允许您封装Query实例。然后,客户机通过包装器与Query通信;包装器控制易变性

    生成器允许您根据需要选择性地添加过滤器。包装器是不可变的,所以在构建包装器之前,我们希望指定可选的过滤器。构建器的构造函数强制客户端传入一个Query实例(每个包装器必须有一个Query