2017-08-02 48 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