![](/img/trans.png)
[英]Java - Create a Card object without enum, with compilation time type checking
[英]Java way to create an object based on enum type
我的課是這樣的:
class X {}
class Y extends X {};
class Z extends X {};
我為每個子類(id +類)都有一個枚舉:
enum Type {
Y_TYPE(1, Y.class), Z_TYPE(2, Z.class);
int id;
Class c;
public Type(int id, Class c) { this.id = id; this.c = c; }
public static X createInstance() throws Exception {
return c.newInstance();
}
}
然后我按如下方式使用它們:
X parseFromID(int id) {
for (Type v : Type.values()) {
if (v.id == id) {
return v.createInstance();
}
}
}
它工作正常,但我想知道這是一種基於Java的方法來基於整數id創建數據嗎? 有什么不好的事情應該尋找嗎?
有沒有一種方法可以強制傳入X類型的類而無需冗長的if-else條件? 想一想當我有大量的子類時。
為什么要使用整數ID?
我正在編寫某種解析器,因此需要將我從某處獲取的整數id轉換為適當的對象。
確實沒有理由在這里使用反射。 拋出異常也是一種不好的做法,並且如果您不使用反射,則不必處理反射異常。 你可以做
enum Type {
Y_TYPE(1) {
@Override
public X createInstance() {
return new Y();
}
}, Z_TYPE(2) {
@Override
public X createInstance() {
return new Z();
}
};
private int id;
private Type(int id) {
this.id = id;
}
public abstract X createInstance();
}
這也很有幫助,因為它不會強制每個子類都具有公共的無參數構造函數,並且如果可能的話,還允許返回相同的X或Y實例。
如果您擔心匿名類定義的冗長性,那么如果使用的是Java 8,則可以用lambda替換它們:
import java.util.function.Supplier;
enum Type {
Y_TYPE(1, X::new), Z_TYPE(2, Y::new);
private int id;
private Supplier<X> supplier;
private Type(int id, Supplier<X> supplier) {
this.id = id;
this.supplier = supplier;
}
public X createInstance() {
return supplier.get();
}
}
使用工廠和地圖更具學術性:
import java.util.HashMap;
import java.util.Map;
interface Factory<T> {
T createInstance();
}
class X {/**/}
class Y extends X {/**/}
class Z extends X {/**/}
class Factories {
static Map<Integer, Factory<?>> factories = new HashMap<>();
static {
factories.put( 1, X::new );
factories.put( 2, Y::new );
factories.put( 3, Z::new );
}
@SuppressWarnings("unchecked")
static <T> Factory<T> get( int id ) {
return (Factory<T>)factories.get( id );
}
}
public class Main {
static void main( String[] args ) {
final Factory<X> fx = Factories.get( 1 );
final X x = fx.createInstance();
final Factory<Y> fy = Factories.get( 2 );
final Y y = fy.createInstance();
final Factory<Z> fz = Factories.get( 3 );
final Z z = fz.createInstance();
}
}
有沒有一種方法可以強制傳入X類型的類而無需冗長的if-else條件?
是的,您可以使用泛型來限制類。 將構造函數更改為:
public Type(int id, Class<? extends X> c) { this.id = id; this.c = c; }
為什么要使用整數ID? 您可以直接使用枚舉值,也可以(如果需要傳輸或存儲它們)使用它們的字符串表示形式,並在需要時使用枚舉的valueOf
方法解析String。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.