使用 Java 动态创建类 [英] Creating classes dynamically with Java
问题描述
我曾试图找到有关此的信息,但空手而归:
I have tried to find information about this but have come up empty handed:
我认为可以使用反射或代理在 Java 中动态创建类,但我不知道如何创建.我正在实现一个简单的数据库框架,我在其中使用反射创建 SQL 查询.该方法获取具有数据库字段的对象作为参数,并基于该对象创建查询.但是,如果我也可以动态地创建对象本身,那将非常有用,这样我就不需要为每个表都有一个简单的数据包装器对象.
I gather it is possible to create a class dynamically in Java using reflection or proxies but I can't find out how. I'm implementing a simple database framework where I create the SQL queries using reflection. The method gets the object with the database fields as a parameter and creates the query based on that. But it would be very useful if I could also create the object itself dynamically so I wouldn't have the need to have a simple data wrapper object for each table.
动态类只需要简单的字段(String
、Integer
、Double
),例如
The dynamic classes would only need simple fields (String
, Integer
, Double
), e.g.
public class Data {
public Integer id;
public String name;
}
这可能吗?我该怎么做?
Is this possible and how would I do this?
这就是我将如何使用它:
This is how I would use this:
/** Creates an SQL query for updating a row's values in the database.
*
* @param entity Table name.
* @param toUpdate Fields and values to update. All of the fields will be
* updated, so each field must have a meaningful value!
* @param idFields Fields used to identify the row(s).
* @param ids Id values for id fields. Values must be in the same order as
* the fields.
* @return
*/
@Override
public String updateItem(String entity, Object toUpdate, String[] idFields,
String[] ids) {
StringBuilder sb = new StringBuilder();
sb.append("UPDATE ");
sb.append(entity);
sb.append("SET ");
for (Field f: toUpdate.getClass().getDeclaredFields()) {
String fieldName = f.getName();
String value = new String();
sb.append(fieldName);
sb.append("=");
sb.append(formatValue(f));
sb.append(",");
}
/* Remove last comma */
sb.deleteCharAt(sb.toString().length()-1);
/* Add where clause */
sb.append(createWhereClause(idFields, ids));
return sb.toString();
}
/** Formats a value for an sql query.
*
* This function assumes that the field type is equivalent to the field
* in the database. In practice this means that this field support two
* types of fields: string (varchar) and numeric.
*
* A string type field will be escaped with single parenthesis (') because
* SQL databases expect that. Numbers are returned as-is.
*
* If the field is null, a string containing "NULL" is returned instead.
*
* @param f The field where the value is.
* @return Formatted value.
*/
String formatValue(Field f) {
String retval = null;
String type = f.getClass().getName();
if (type.equals("String")) {
try {
String value = (String)f.get(f);
if (value != null) {
retval = "'" + value + "'";
} else {
retval = "NULL";
}
} catch (Exception e) {
System.err.println("No such field: " + e.getMessage());
}
} else if (type.equals("Integer")) {
try {
Integer value = (Integer)f.get(f);
if (value != null) {
retval = String.valueOf(value);
} else {
retval = "NULL";
}
} catch (Exception e) {
System.err.println("No such field: " + e.getMessage());
}
} else {
try {
String value = (String) f.get(f);
if (value != null) {
retval = value;
} else {
retval = "NULL";
}
} catch (Exception e) {
System.err.println("No such field: " + e.getMessage());
}
}
return retval;
}
推荐答案
可以生成类(通过 cglib、asm、javassist, bcel),但你不应该那样做.为什么?
It is possible to generate classes (via cglib, asm, javassist, bcel), but you shouldn't do it that way. Why?
- 使用库的代码应该期望
Object
类型并使用反射获取所有字段 - 不是一个好主意 - java 是静态类型语言,您想引入动态类型 - 这不是地方.
- the code that's using the library should expect type
Object
and get all the fields using reflection - not a good idea - java is statically typed language, and you want to introduce dynamic typing - it's not the place.
如果你只是想要一个未定义格式的数据,那么你可以在一个数组中返回它,比如Object[]
,或者Map
,如果您希望它们命名,并从那里获取它 - 它会为您节省不必要的类生成的麻烦,其唯一目的是包含一些将通过反射获得的数据.
If you simply want the data in an undefined format, then you can return it in an array, like Object[]
, or Map<String, Object>
if you want them named, and get it from there - it will save you much trouble with unneeded class generation for the only purpose of containing some data that will be obtained by reflection.
您可以做的是使用预定义的类来保存数据,并将它们作为参数传递给查询方法.例如:
What you can do instead is have predefined classes that will hold the data, and pass them as arguments to querying methods. For example:
public <T> T executeQuery(Class<T> expectedResultClass,
String someArg, Object.. otherArgs) {..}
因此,您可以对传递的 expectedResultClass
使用反射来创建该类型的新对象并用查询结果填充它.
Thus you can use reflection on the passed expectedResultClass
to create a new object of that type and populate it with the result of the query.
也就是说,我认为您可以使用现有的东西,例如 ORM 框架(Hibernate、EclipseLink)、spring 的 JdbcTemplate
等.
That said, I think you could use something existing, like an ORM framework (Hibernate, EclipseLink), spring's JdbcTemplate
, etc.
这篇关于使用 Java 动态创建类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!