动态创建字段和方法

时间:2013-08-16 14:11:51

标签: java

我想为给定的类添加新字段(变量)和封装方法。例如:班级名称学生没有以下任何字段:

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:谢谢你们所有人的回答并获得了许多信息和想法。并改变了从你的建议到更好的道路的方式

7 个答案:

答案 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)

为此,您可以使用JavassistASM等字节码检测库。 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)是最好的选择。