2017-08-02 448 views
1

我有一个Java项目,我有2个类。我需要使用Java反射来首先打印由构造函数ProjectAccount.javamywork.java类设置的默认值,然后我需要重写toString()方法以传递mywork.java类的值并打印它们。使用Java反射覆盖另一个类的方法

我能够使用java反射来打印默认的构造函数集值。但是在尝试覆盖并使用参数打印toString()方法时出现错误。

ProjectAccount.java

package relive; 

public class ProjectAccount { 
    private String projectAccountID; 
    private double budget; 
    public int noOfProjects; 

    public ProjectAccount(){ 
     this.projectAccountID = "MARTINDAWS-BillAnalyzer-001"; 
     this.budget = 120000.00; 
     this.noOfProjects = 10; 
    } 

    @Override 
    public String toString(){ 
     return "Project Accoutn ID = " + projectAccountID + " , Project Budget = "+budget + " , No of Projects = "+ noOfProjects; 
    } 
} 

mywork.java

package relive; 

import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 

public class mywork { 

    public static void main(String[] args) { 
     try{ 
      Class<?> clazz = Class.forName("relive.ProjectAccount"); 
      Constructor<?> constr = clazz.getDeclaredConstructor(null); 
      Method mets = clazz.getDeclaredMethod("toString", null); 
      Object obj = constr.newInstance(new Object[] {}); 

      //Print Default values 
      System.out.println(mets.invoke(obj, null)); 

      String mod_projectAccountID="ORPT-BT-EMP-DEV"; 
      double mod_budget = 2200000.0; 
      int mod_noOfProjects = 20; 

      //Print new passed values using the overridden method 
      System.out.println(mets.invoke(obj, mod_projectAccountID,mod_budget, mod_noOfProjects));   
     } 

     catch(ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e){ 
      e.printStackTrace(); 
     } 
    } 
    public static String toString(String mod_projectAccountID, double mod_budget, int mod_noOfProjects){ 
     return "Project Accoutn ID = " + mod_projectAccountID + " , Project Budget = "+mod_budget + " , No of Projects = "+ mod_noOfProjects; 
    } 

} 

输出和错误

output

我想我遇到了这个错误,因为我还没有重写toString()方法。任何关于如何覆盖和打印此建议将受到高度赞赏。

+0

目前尚不清楚为什么你故意试图调用方法与更多的元素比它可以采取。 mets的定义与没有参数的ProjectAccount toString方法完全相同。 myWork类不扩展ProjectAccount,那么它的toString方法如何以任何方式覆盖ProjectAccount实现? – Assafs

+0

因此,我可以直接访问变量并修改它们的值并调用相同的'toString()'方法,而不是试图覆盖并传递修改的参数。 –

+0

当您使用反射时,您无法更改任何方法的签名 - 您只能在定义时调用它们。所以ProjectAccount方法toString()将永远不会接受任何参数。如果你想让它接受更多的参数,你的选择是:1)在Project Account中写入另一个toString方法,它需要参数(你可以保留原来的toString()方法,只需添加另一个新方法)。 2)让ProjectAccount扩展myWork - 这将允许你使用带有参数的myWork版本的toString。 – Assafs

回答

0

这里有几个问题。

  1. 覆盖的toString是通过定义一个实例方法(你是静态的)
  2. 你的反射访问是mets,它引用ProjectAccount
  3. mywork不是ProjectAccount
  4. 子类中,你可以” t添加参数,

子类覆盖上午的能力ethod允许类从行为足够“接近”的超类继承,然后根据需要修改行为。重写方法具有相同的名称,参数的数量和类型,以及返回类型与其覆盖的方法相同。重写方法也可以返回重写方法返回的类型的子类型。这个子类型称为协变返回类型。

Oracle Docs

package de.me.example; 

public class SuperType { 

    @Override 
    public String toString() { 

     return "SuperType"; 
    } 

} 


package de.me.example; 

public class SubType extends SuperType { 

    // this annatotion is syntactic sugar nothing more, 
    //it behaves the same without it 
    @Override 
    public String toString() { 
     return "SubType"; 
    } 

} 
+0

在这种情况下,我是否要在同一个try {}块中声明该方法并添加@Override?你能举出一个基于此的例子吗?谢谢 –

+0

你能澄清一下,你真正想要得到什么?我明白,你想重写一个toString追加方法参数? –

0

我只是修改了mywork.java类直接访问ProjectAccount.java类变量和设置。

我访问了声明的字段,并根据变量的名称或类型修改了声明的变量,并调用了相同的toString()方法,而不用重写toString()方法。

mywork。java的

package relive; 

import java.lang.reflect.Constructor; 
import java.lang.reflect.Field; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 

public class answer_a { 

    public static void main(String[] args) { 
     try{ 
      Class<?> clazz = Class.forName("relive.ProjectAccount"); 
      Constructor<?> constr = clazz.getDeclaredConstructor(null); 
      Method mets = clazz.getDeclaredMethod("toString", null); 
      Object obj = constr.newInstance(new Object[] {}); 

      //Print Default values 
      System.out.println(mets.invoke(obj, null)); 

      String mod_projectAccountID= "ORPT-BT-EMP-DEV"; 
      double mod_budget = 2200000.0; 
      int mod_noOfProjects = 20; 

      //Method that accesses the Fields and modifies them with the new variables 

      Field [] fields = clazz.getDeclaredFields(); 
      for(int y=0; y<fields.length; y++){ 
       fields[y].setAccessible(true); 

       if(fields[y].getName() == "projectAccountID"){ 
        fields[y].set(obj, mod_projectAccountID); 
       } 
       else if(fields[y].getType().getSimpleName() == "double"){ 
        fields[y].set(obj, mod_budget); 
       } 
       else if (fields[y].getType().getSimpleName() == "int"){ 
        fields[y].set(obj, mod_noOfProjects); 
       } 
      } 

      System.out.println(mets.invoke(obj, null)); 

     } 
     catch(ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e){ 
      e.printStackTrace(); 
     } 
    } 

} 

输出

output