2016-12-03 2 views
2

Я только начал использовать javassist, и я не могу понять, как создать экземпляр класса, созданного во время выполнения.Как создать экземпляр класса, созданного во время выполнения с помощью javassist?

Метод makeNewClass() делает NewClass класс так:

public bin.objects.base.NewClass { 
    public int quantity = 5; 
    private float weight = 30.25f; 

    public float getWeight() { return weight; } 
    public void setWeight(float weight) { this.weight = weight; } 
    public float totalWeight() { return quantity * getWeight(); } 
} 

Этот метод работает просто отлично:

public void makeNewClass() throws NotFoundException, IOException, CannotCompileException { 
     // ClassMaker maker holds the CtClass object and handles all the "making" 
     ClassMaker maker = new ClassMaker("bin.objects.base.NewClass"); 

     maker.addField(CtClass.intType, "quantity", "5", Modifier.PUBLIC); 
     maker.addField(CtClass.floatType, "weight", "30.25f", Modifier.PRIVATE); 

     maker.addMethod(Modifier.PUBLIC, CtClass.floatType, "totalWeight", null, null, 
       "{ return quantity * getWeight(); }", null, MethodType.standard); 
     maker.getCtClass().writeFile(); 
    } 

Теперь начинается проблема. Этот метод должен создать экземпляр NewClass, получить доступ к его полям e, чтобы вызвать его методы.

public void testNewClass() 
      throws Throwable { 
     CtClass ctclass = ClassPool.getDefault().get("bin.objects.base.NovaClasse"); 

     Object testClass = ctclass.toClass(new Loader(), null); 

     // Throws NoSuchFieldException 
     Field q = testClass.getClass().getDeclaredField("quantity"); 
     int quantity = (int) q.get(testClass); 

     Class[] cArg = new Class[1]; 
     cArg[0] = Float.class; 

     // Throws NoSuchMethodException 
     Method m = testClass.getClass().getDeclaredMethod("getWeight", cArg); 
     float weight = (float) m.invoke(testClass, null); 

     // Throws NoSuchMethodException 
     m = testClass.getClass().getDeclaredMethod("totalWeight", cArg); 
     float totalWeight = (float) m.invoke(testClass, null); 

     System.out.println("quantity = " + quantity + 
       "weight = " + weight + 
       "totalWeight = " + totalWeight); 
    } 

Теперь я уже понял, что TestClass это фактически инициализируется как экземпляр java.lang.Class, не bin.objects.base.NewClass. Поэтому, очевидно, он не найдет поля и методы NewClass.

Вопрос в том, как я могу это решить? Я пробовал использовать метод java.lang.Class.cast(), но не имел успеха.

+0

код, кажется, половина переведена половина или может быть jumbling с именами переменных. Не могли бы вы это исправить. – nullpointer

+0

Несомненно. Я пропустил несколько имен в переводе. Я думаю, теперь все в порядке. –

ответ

1

Наконец-то я смог выяснить, в чем проблема.

По-видимому, это была проблема с ClassLoader. Я нашел ответ in this post. Чтобы решить эту проблему, я просто включил эту строку:

Class newClasse = ctclass.toClass(this.getClass().getClassLoader(), 
    this.getClass().getProtectionDomain()); 

@ ответ nullpointer также помог.

Таким образом, после того, как еще несколько изменений, метод testNewClass() кончался так:

public void testNewClass() 
      throws Throwable { 
     CtClass ctclass = ClassPool.getDefault().get("bin.objects.base.NewClass"); 
     Class newClass = ctclass.toClass(this.getClass().getClassLoader(), 
      this.getClass().getProtectionDomain()); 
     Object objNewClass = newClass.newInstance(); 

     System.out.println("Accessing the field 'public int quantity'..."); 
     Field q = newClass.getDeclaredField("quantity");   
     int quantity = (int) q.get(objNewClass); 
     System.out.println("quantity = " + quantity); 

     System.out.println("\nAccessing the field 'private float weight' " + 
      "through the method 'public float getWeight()'..."); 
     Method m = newClass.getDeclaredMethod("getWeight", null); 
     float weight = (float) m.invoke(objNewClass, null); 
     System.out.println("weight = " + weight); 

     System.out.println("\nAccessing the method 'public float totalWeight()'..."); 
     m = newClass.getDeclaredMethod("totalWeight", null); 
     float totalWeight = (float) m.invoke(objNewClass, null);   
     System.out.println("totalWeight = " + totalWeight); 
    } 
0

Попробуйте использовать отражение, чтобы получить объект класса, как:

Field q = Class.forName("bin.objetos.base.NovaClasse").getDeclaredField("quantity"); 

Вы можете сделать то же самое для других областей.

+0

Не работает. Он выдает «ClassNotFoundException». Но все равно спасибо. –

+0

@BrunoNascimento Загрузили ли вы класс через загрузчик классов? –

+0

confused from question, попробуйте с 'Class.forName (" bin.objetos.base.NewClass ")' один раз, пожалуйста, – nullpointer