2017-10-17 50 views
0

我有一個接口getDeclaredConstructor不會界面找到構造函數參數

public interface IDrawing 

接下來我有實現這個接口的類:

public class Line implements IDrawing 

現在我有一個類,它接受一個構造函數以上作爲參數:

public LineChanger(Line line) 

那裏沒問題。

當我使用反射上面的構造函數調用,它拋出一個NoSuchMethodException

//drawing variable is of class Line implementing IDrawing 
.getDeclaredConstructor(IDrawing.class).newInstance(drawing); 

異常消失時,我改變構造函數:

public LineChanger(IDrawing line) 

是否有可能得到反映工作而不改變構造函數?

我希望保持構造函數嚴格(即在這種情況下只接受一個特定的類Line),但保持反射對我的工廠工作。

+4

構造函數只接受'Line'對象。沒有任何構造函數可以接受任何'IDrawing',所以當你試圖用反射來獲得一個異常時,你會得到一個Exception並不奇怪。 –

回答

2
public LineChanger(Line line) 

當我使用反射上面構造函數調用,它拋出一個NoSuchMethodException

只有當你聽錯了。

//drawing variable is of class Line implementing IDrawing 
.getDeclaredConstructor(IDrawing.class).newInstance(drawing); 

你說錯了。參數的類型是Line.class,而不是IDrawing.class

異常消失時,我改變構造函數:

public LineChanger(IDrawing line) 

當然它中。當你這樣做時,你的Java代碼和你的反射代碼是一致的。如果他們不這樣做,它不能工作,可以嗎?

是否可以在不更改構造函數的情況下使反射工作?

是的,叫.getDeclaredConstructor(Line.class).newInstance(drawing);,提供drawingLine一個實例。

你似乎在期待奇蹟在這裏。

+0

乾杯@EJP我不知道今天早上我的大腦在哪裏,它一定還躺在牀上...謝謝你清理東西!我會繼續討論這個話題,因爲Sweeper和Royal Bg的回覆仍然很有趣 –

1

當您調用getConstructor時,API將查找具有該簽名的構造函數,因此如果沒有構造函數採用IDrawing參數,則代碼將引發異常。

無論如何API沒有任何意義。您不能將IDrawing類型的對象傳遞給Line類型的參數,因爲您傳遞的對象可以是IDrawing的任何實現。

但是,反過來也是可以的,您可以將類型爲Line的對象傳遞給構造函數,其格式爲IDrawing。這裏有一個方法可以找到給定的一組類型可以傳遞給的所有構造函數。

public static List<Constructor<?>> getCompatibleConstructors(Class<?> clazz, Class<?>... parameterTypes) { 
    Constructor<?>[] ctrs = clazz.getConstructors(); 
    ArrayList<Constructor<?>> list = new ArrayList<>(); 
    outer: for (Constructor<?> ctr : ctrs) { 
     if (ctr.getParameterCount() == parameterTypes.length) { 
      for (int i = 0 ; i < parameterTypes.length ; i++) { 
       if (!ctr.getParameterTypes()[i].isAssignableFrom(parameterTypes[i])) { 
        continue outer; 
       } 
      } 
      list.add(ctr); 
     } 
    } 
    return list; 
} 

它可以找到這個構造函數:如果您通過這些參數

public MyClass(IDrawing drawing) {} 

getCompatibleConstructors(MyClass.class, Line.class); 
1

有可能使你想要的方式,如果你遍歷所有構造函數和找到一個具有可從IDrawing分配的參數的參數。

Constructor ctor = Arrays.stream(LineChanger.class.getConstructors()) 
      .filter(c -> c.getParameterCount() == 1) 
      .filter(c -> c.getParameterTypes()[0].isAssignableFrom(IDrawing.class)) 
      .findFirst() 
      .orElse(LineChanger.class.getConstructors()[0]);