簡體   English   中英

基於枚舉類型創建對象的Java方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM