我正在嘗試創建一個通用方法來處理 Java 中不同型別的 ArrayList。這些型別完全不同,但都包含一個相同的引數,我想在此方法中對其進行評估。
但是我不能ArrayList<type>用給定的類資訊創建正確的。
我究竟做錯了什么?
private String test(ArrayList<?> list, Class<?> type) {
for(type i : list){ // for (type i : (ArrayList<type>) list){
// do something
}
return "xxx"
}
private void init() {
ArrayList<Type_1> a1 = new ArrayList<>();
ArrayList<Type_2> a2 = new ArrayList<>();
String s1 = test(a1, Type_1.class);
String s2 = test(a2, Type_2.class);
}
更新 找到解決方案
private String test(ArrayList<?> list) {
for (Object i : list){
try {
Method m = i.getClass().getMethod("getName", null);
System.out.println(m.invoke(i));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//Handle Exception
}
}
}
uj5u.com熱心網友回復:
您需要宣告一個顯式型別引數:
private <T> String test(ArrayList<T> list, Class<T> type) {
for (T i : list) {
// do something with 'i'
}
return "xxx"
}
如果你不需要Class<T>爭論,你可以忽略它;例如
private <T> String test(ArrayList<T> list) {
for (T i : list) {
// do something
}
return "xxx"
}
Class<T> type如果您打算創建該類的實體...或該類的陣列,通常只需要傳遞一個物件。
注釋掉的代碼版本不會編譯,因為它混合了編譯時和運行時型別。在
for (type i : (ArrayList<type>) list) {
編譯器需要知道type在編譯時代表什么型別。但它是一個運行時變數。但這甚至在此之前也是無效的,因為 Java 語法在那時需要型別的識別符號......而不是變數的識別符號。
uj5u.com熱心網友回復:
我創建了一個與這兩種解決方案相關的混合答案:
實作介面
第一個是通過一個簡單的介面MyType來完成的,該介面定義了類Type_1和Type_2. 這是干凈且正確的 Java 方式。這樣編譯器就會告訴你是否可以執行某些操作。這也表明初學者在實施想法的概念上存在問題。
缺點是所有類都必須實作該介面(可以在其繼承層次結構的任何地方定義)。
但是 Java 完全是關于型別安全和編譯器警告的優勢。所以這顯然是首選方式。
使用反射
可以使用反射來完成這項任務,是的。但不一定是個好主意。使用反射,存在多個問題:
- 您將收到運行時錯誤或必須處理這些例外
- 專案將開始,但如果你的設計、你的概念有缺陷,這將很難確定
- 許多庫不能很好地處理反射(面向方面??的編程、應用程式容器、GraalVM NativeImage 等特殊編譯器等)
- 使用反射會更慢并消耗更多記憶體
因此,如果遠離反射是可能且容易的,您應該避開。特別是如果這有一個如此簡單的適當解決方案。
(我還用反射清理了你的代碼,那里有一些小的不一致,不會讓它編譯)
代碼:
package stackoverflow;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class SimpleInterfacing {
interface MyType {
String getName();
}
static class Type_1 implements MyType {
@Override public String getName() {
return "This is type 1";
}
}
static class Type_2 implements MyType {
@Override public String getName() {
return "This is type 2";
}
}
private String test(final ArrayList<? extends MyType> list) {
String returnValue = null;
for (final MyType t : list) {
// do something
System.out.println("Got name: " t.getName());
returnValue = t.getName();
}
return returnValue; // returns last value, null is lists are empty
}
private void init() {
final ArrayList<Type_1> a1 = new ArrayList<>();
a1.add(new Type_1());
final ArrayList<Type_2> a2 = new ArrayList<>();
a2.add(new Type_2());
{
final String s1 = test(a1);
System.out.println("s1 is " s1);
}
{
final String s2 = test(a2);
System.out.println("s2 is " s2);
}
{
test_reflection(a1);
test_reflection(a2);
}
}
public static void main(final String[] args) {
new SimpleInterfacing().init();
}
private String test_reflection(final ArrayList<?> list) {
for (final Object i : list) {
try {
final Method m = i.getClass().getMethod("getName");
System.out.println("Invoked: " m.invoke(i));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//Handle Exception
ex.printStackTrace();
}
}
return null;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/475578.html
