10

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

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:感谢大家的回答并获得了许多信息和想法。并根据您的建议改变了通往更好道路的方式

4

7 回答 7

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对象本身和两种方法,坦率地说,这是一个公平的权衡,以获得更整洁的解决方案。

于 2013-08-16T14:16:15.243 回答
3

为此,您可以使用JavassistASM等字节码检测库。下面是使用 Javassist 添加字段或方法的示例

于 2013-08-16T14:17:30.673 回答
1

虽然字节码操作是可能的,但这并不明智,特别是如果您打算这样做以“节省内存”。您不太可能拥有如此多的数据以至于它会有所作为,如果您这样做了,您无论如何都会将它们存储在数据库中。

于 2013-08-16T14:16:00.653 回答
1

HashMap您可以使用DynaBean 和 DynaClass代替编写自己的解决方案:不仅支持简单的属性,还支持索引(Array)和映射(Map)。
DynaBean 可以自省以获取属性和值,因此您可以转储到文件 使用此解决方案您只是“模拟”一个 bean,您的Student类实际上并不包含字段和访问器(您调用Student.getClass().getDeclaredField()您将获得一个空数组)。

如果您需要编写一个“真正的”java java.lang.ClassJavassist(我的首选,我曾经解决类似于您的问题的解决方案)或 ASM(或 CGLIB)是最好的选择。

于 2013-08-16T14:38:50.337 回答
0

实际上,不是在 Java 中。在 Javascript 等其他语言中,这是可能的。

于 2013-08-16T14:13:21.323 回答
0

我不相信这在java中是否可行,但我确信它只会添加到内存中,因为如果你动态添加它们,它们必须事先设置+动态添加它们的代码。

于 2013-08-16T14:16:00.710 回答
0

Java 不是一种动态编程语言,因此即使某些高级方法可能允许您这样做,我也不建议您遵循该路线。

该场景的 Java 习惯用法是将字段值存储在(散列)映射中。因此,您将有几个通用访问器来设置或获取所有属性值,并且在访问器中您需要指示要更改的属性的名称。

但是,除非属性的最大数量相当大并且大多数对象仅具有少量此类属性的值,否则此解决方案不会节省内存。

   public class Entity {
   
      // 5 is an estimate for the number attrs.
      private Map<String,Object> attrs = new HashMap<>(5); 

      public Object getAttribute(String name) { return attrs.get(name); }

      public void setAttribute(String name, Object obj) { attrs.put(name,obj); } 

   }

如果您管理有关可能属性及其值类型的元数据,您可以实现一些运行时类型检查。

于 2013-08-16T14:31:50.513 回答