Java 动态创建字段和方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18275360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create Fields and methods dynamically
提问by Débora
I want to add new fields(variables) and encapsulating methods for a given class. For example: A class name Student has no any fields like below:
我想为给定的类添加新的字段(变量)和封装方法。例如:班级名称 Student 没有任何字段,如下所示:
public class Student implements Serializable{
}
then in my application an instance is created;
然后在我的应用程序中创建了一个实例;
Student s=new Student();
I want to add new methods which do not exist for student class at the run time.for example: I want to add a field called studentName
, and getStudentName()
and setStudentName()
methods.
我想添加在运行时学生类不存在的新方法。例如:我想添加一个名为studentName
,getStudentName()
和setStudentName()
方法的字段。
Then at the run time the student object will be like this;
那么在运行时学生对象会是这样的;
public class Student implements Serializable{
private String studentName;
public void setStudentName(..){}
public String getStudentName(){return ...;}
}
In my application objects are written to a text file and all objects of same type do not have all variables. Therefore, I want to add only the required fields to save memory.
在我的应用程序中,对象被写入一个文本文件,并且所有相同类型的对象都没有所有变量。因此,我只想添加必需的字段以节省内存。
Any way is there a way to do this? Any sample code or link?
有没有办法做到这一点?任何示例代码或链接?
EDIT: or else can we create a class either and create instances which does not exists ?
编辑:否则我们可以创建一个类并创建不存在的实例吗?
EDIT 2: Thanks all of you answered and got many info and ideas. And changed the way to a better path from your suggestions as well
编辑 2:感谢你们所有人的回答并获得了许多信息和想法。并从你的建议中改变了一条更好的道路
采纳答案by christopher
Why not just create a HashMap
of values? Much more efficient, and has all the flexibility you're looking for.
为什么不只是创建一个HashMap
值?效率更高,并具有您正在寻找的所有灵活性。
public class Student
{
private HashMap<String, String> values;
public Student()
{
this.values = new HashMap<String, String>();
}
public void addValue(String name, String value)
{
values.put(name, value);
}
public String getValue(String name)
{
return values.get(name);
}
}
Why a HashMap?
为什么是 HashMap?
You said that all objects may have differing values, and you'll be defining those new methods and attributes by a String
. Well.. this will achieve that functionality without any horrible bytecode manipulation. For example:
您说过所有对象可能具有不同的值,并且您将通过String
. 嗯..这将实现该功能而无需任何可怕的字节码操作。例如:
String attrName = "name";
String attrValue = "jim";
Student stu = new Student();
stu.addValue(attrName, attrValue);
At the moment, you've only got the one value in your HashMap
. The only overheard you have to face is the HashMap
object itself, and two methods, which frankly is a fair trade off for a far tidier solution.
目前,您的HashMap
. 您必须面对的唯一听到的是HashMap
对象本身和两种方法,坦率地说,这是对更整洁的解决方案的公平权衡。
回答by Brad
Practically speaking,not in Java. In other languages like Javascript, this is possible.
实际上,不是在 Java 中。在其他语言(如 Javascript)中,这是可能的。
回答by Mihai Bratulescu
I dont believe if this is possible in java but I'm sure it will only add to the memory because if you add them dynamically they must be set up beforehand + the code to add them dynamically.
我不相信这在 Java 中是否可行,但我确定它只会添加到内存中,因为如果您动态添加它们,则必须事先设置它们 + 动态添加它们的代码。
回答by Kayaman
While it is possible with bytecode manipulation and such it wouldn't be wise, especially if you intend to do this to "save memory". It's unlikely that you would have so much data that it would make a difference, and if you did, you would store them in a database anyways.
虽然字节码操作是可能的,但这样做并不明智,特别是如果您打算这样做以“节省内存”。您不太可能拥有如此多的数据以致于产生影响,如果您这样做了,您无论如何都会将它们存储在数据库中。
回答by Santosh
回答by Valentin Ruano
Java is not a dynamic programming language and so I would not advice to follow that route even if some advance approaches may allow you to do so.
Java 不是动态编程语言,因此即使某些高级方法可能允许您这样做,我也不建议遵循该路线。
The Java idiom for that scenario would be to store the field values in a (hash) map instead. So you would have a couple of common accessors to set or get all attribute values and in the accessor you would need to indicate the name of the attribute you want to change.
该场景的 Java 习惯用法是将字段值存储在(哈希)映射中。因此,您将有几个通用访问器来设置或获取所有属性值,并且您需要在访问器中指明要更改的属性的名称。
However this solution won't save memory unless the maximum number of attributes is rather large and most object just have values for a small number of such attributes.
然而,除非属性的最大数量相当大并且大多数对象只有少量此类属性的值,否则此解决方案不会节省内存。
public class Entity {
// 5 is an estimate for the number attrs.
private Map<String,?> attrs = new HashMap<>(5);
public Object getAttribute(String name) { return attrs.get(name); }
public void setAttribute(String name, Object obj) { attrs.put(name,obj); }
}
You could implement some runtime type-checking if you manage meta-data about possible attributes and their value types.
如果您管理有关可能的属性及其值类型的元数据,则可以实施一些运行时类型检查。
回答by Luca Basso Ricci
Instead of writing your own HashMap
based solution you can use DynaBean and DynaClass: support not only simple properties but also indexed (Array) and mapped (Map).
DynaBean can be introspected to get properties and values so you can dump to file BUTwith this solution you are only "simulating" a bean, your Student
class doesn't really contains fields and accessors (you you call Student.getClass().getDeclaredField()
you will get an empty array).
HashMap
您可以使用DynaBean 和 DynaClass代替编写自己的基于解决方案:不仅支持简单的属性,还支持索引(Array)和映射(Map)。
可以内省 DynaBean 以获取属性和值,因此您可以转储到文件但是使用此解决方案您只是“模拟”一个 bean,您的Student
类并不真正包含字段和访问器(您调用Student.getClass().getDeclaredField()
您将获得一个空数组)。
If you need to compose a "real" java java.lang.Class
Javassist (my preferred choice, I used to resolve a solution similar to your question) or ASM (or CGLIB) are the best choiches.
如果您需要编写一个“真正的”java java.lang.Class
Javassist(我的首选,我曾经解决过类似于您的问题的解决方案)或 ASM(或 CGLIB)是最好的选择。