我想为给定的类添加新字段(变量)和封装方法。例如:班级名称学生没有以下任何字段:
public class Student implements Serializable{
}
然后在我的应用程序中创建一个实例;
Student s=new Student();
我想在运行时添加学生类不存在的新方法。例如:我想添加一个名为studentName
的字段,以及getStudentName()
和setStudentName()
方法
然后在运行时,学生对象将是这样的;
public class Student implements Serializable{
private String studentName;
public void setStudentName(..){}
public String getStudentName(){return ...;}
}
在我的应用程序中,对象被写入文本文件,所有相同类型的对象都没有所有变量。因此,我只想添加必要的字段以节省内存。
有没有办法做到这一点?任何示例代码或链接?
编辑:或者我们可以创建一个类并创建不存在的实例吗?
编辑2:谢谢你们所有人的回答并获得了许多信息和想法。并改变了从你的建议到更好的道路的方式答案 0 :(得分:7)
为什么不创建一个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);
}
}
为什么要使用HashMap?
您说所有对象可能具有不同的值,您将通过String
定义这些新方法和属性。嗯..这将实现该功能,没有任何可怕的字节码操作。例如:
String attrName = "name";
String attrValue = "jim";
Student stu = new Student();
stu.addValue(attrName, attrValue);
目前,您只有HashMap
中的一个值。唯一无意中听到的是HashMap
对象本身,以及两种方法,坦率地说,这是一个更为简洁的解决方案的公平交易。
答案 1 :(得分:3)
为此,您可以使用Javassist或ASM等字节码检测库。 Here is an example使用Javassist添加字段或方法。
答案 2 :(得分:1)
虽然可以使用字节码操作,但这样做并不明智,特别是如果你打算这样做以“节省内存”。您不太可能拥有如此多的数据以至于它会产生重大影响,如果您这样做,则无论如何都会将它们存储在数据库中。
答案 3 :(得分:0)
实际上,不是Java。在其他语言如Javascript中,这是可能的。
答案 4 :(得分:0)
我不相信如果这在java中是可行的,但我确信它只会添加到内存中,因为如果你动态添加它们,必须事先设置它们+动态添加它们的代码。
答案 5 :(得分:0)
Java不是一种动态编程语言,所以即使有一些先进的方法可能允许你这样做,我也不建议遵循这条路线。
该场景的Java习惯用法是将字段值存储在(哈希)映射中。因此,您可以使用几个常用访问器来设置或获取所有属性值,而在访问器中,您需要指明要更改的属性的名称。
但是,除非最大数量的属性相当大,并且大多数对象只有少量此类属性的值,否则此解决方案不会节省内存。
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); }
}
如果管理有关可能属性及其值类型的元数据,则可以实现一些运行时类型检查。
答案 6 :(得分:0)
您可以使用DynaBean and DynaClass而不是编写自己的HashMap
解决方案:不仅支持简单属性,还支持索引(数组)和映射(地图)。
可以对DynaBean进行内省以获取属性和值,以便您可以转储到文件但
使用此解决方案,您只是“模拟”一个bean,您的Student
类并不真正包含字段和访问者(您调用Student.getClass().getDeclaredField()
将得到一个空数组。)
如果您需要撰写一个“真正的”java java.lang.Class
Javassist(我的首选,我曾经解决类似于您的问题的解决方案)或ASM(或CGLIB)是最好的选择。