以下是我如何在運行時根據要呼叫的子類設法構造建構式物件(以避免每次要添加新子類時都必須更新 Factory 類):
import java.lang.reflect.InvocationTargetException;
public class Main{
private static final class X{}
private static abstract class A{
public A(X x){}
public static A newInstance(Class<? extends A> subType, X x) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
return subType.getConstructor(X.class).newInstance(x);
}
}
private static final class A_1 extends A{
public A_1(X x){
super(x);
//...
}
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
for(int i = 0; i < 1000; i ){
X x = new X();
long t = System.currentTimeMillis();
A a = A.newInstance(A_1.class, x);
t = System.currentTimeMillis() - t;
System.out.println(t);
}
}
}
起初我認為它會很慢,但我在第一次迭代中獲得 1ms 并且在任何連續實體化中獲得 0。
一旦我的應用程式被部署,我是否可以期待類似的行為(在這里我簡化了程序,但在我的應用程式背景關系中幾乎沒有任何困難)。
做這種技術的利弊是什么?
uj5u.com熱心網友回復:
反思幾乎總是最糟糕的做事方式。
- 反思很慢。它通常無法在運行時被實時編譯器優化。
- 反射很容易出錯。編譯器無法驗證反射代碼的正確性。在您的情況下,編譯器不能保證
subType具有采用單個 X 引數的建構式。 - 反射很難在代碼中遵循,因此很難維護。
在您的情況下,您需要一個代表子類構造函式的函式:
public static A newInstance(Function<? super X, ? extends A> constructor, X x) {
return constructor.apply(x);
}
您將使用方法參考呼叫該方法:
A a = newInstance(A_1::new, x);
uj5u.com熱心網友回復:
當然,反射不是基本情況(但它絕對有效)。我提供用于Factory保存所有工廠方法以創建所需型別。只需添加向實作添加新工廠的功能,而無需更改它。
我提供了一個無需更改您的主要 API 的解決方案public static <T extends Base> T newInstance(Class<T> subType, X x)。
public class Main {
public static void main(String[] args) throws Exception {
Factory.add(OneBase.class, OneBase::new);
Factory.add(TwoBase.class, TwoBase::new);
OneBase oneBase = Factory.newInstance(OneBase.class, new X());
TwoBase twoBase = Factory.newInstance(TwoBase.class, new X());
}
}
final class Factory {
private static final Map<Class<? extends Base>, Function<X, ? extends Base>> FACTORIES = new HashMap<>();
public static void add(Class<? extends Base> subType, Function<X, ? extends Base> factory) {
FACTORIES.put(subType, factory);
}
public static <T extends Base> T newInstance(Class<T> subType, X x) {
return (T)FACTORIES.get(subType).apply(x);
}
}
final class X {}
abstract class Base {
protected Base(X x) {}
}
final class OneBase extends Base {
public OneBase(X x) {
super(x);
}
}
final class TwoBase extends Base {
public TwoBase(X x) {
super(x);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/345305.html
上一篇:盡管回傳條件為真,函式也不會回傳
下一篇:如何使變數隨處可訪問?
