2014-11-04 65 views
1

我一直在試圖生成從1開始,像這樣的類實例的唯一ID:生成獨特的自動遞增的實例ID

public abstract class foo { 
    static int ID = 0; 
    final int id; 

    public foo() { this.id = ++ID; } 
} 

我才明白,我有需要此行爲的若干類等我試圖從中繼承一個abstract class,但我發現static字段不能真正被繼承。

有沒有什麼方法可以在Java中重用這種常見行爲?

編輯:
我沒有說清楚,但我需要的索引每個子類是不僅造型獨特,而且是連續的。

舉例來說,如果我有barbazfoo繼承:

bar b1 = new bar(); 
baz b2 = new baz(); 
bar b3 = new bar(); 

b2應該有id == 1,並b3應該有id == 2

+0

可能重複[Java的給予對象的每個實例的唯一編號(http://stackoverflow.com/questions/21708765/java-give-每個對象一個唯一編號) – 2014-11-04 21:33:31

+0

不,它通常是按類(或類的層次結構)進行的。而且你不應該抽象類,因爲你需要一個計數器 – 2014-11-04 21:34:24

+0

@RC。這不是該問題的重複。這個問題是關於如何在多個類中重用(已經理解的)行爲。 – 2014-11-04 21:40:55

回答

0

不是真的!有幾件事你可以嘗試:

  1. 有一個單一的IDGenerator類與靜態方法來生成一個特定的類的新ID。 .generate()方法將採用Class<?>參數,並將映射類保留到最近給出的標識符。這將把所有的邏輯放到一個類中,但不會真正簡化。
  2. 在每個想要使用這種行爲的類中有一個IDGenerator類的新實例的靜態引用。在這種情況下,IDGenerator類不需要Class<?>參數,因爲每個使用它的類都有一個實例。其方法.generate()將是一種無參數方法。再次,我不確定這會讓事情變得更簡單。
  3. 放棄連續ID的要求。這樣,你可以有一個類IDGenerator與靜態無參數.generate()方法,它只是放棄下一個未使用的標識符。然後,您的標識符在您的應用程序中將是唯一的,而不是在班級中連續使用。

你有什麼是相當傻瓜和苗條。

還有一點小問題:你說你想讓你的ID從0開始,但是你寫它的方式,他們將從1開始。你想要this.id = ID++而不是this.id = ++ID

+0

這是一個錯誤。我的意思是他們打算從1.開始編輯。並且感謝您理解我的意思,即使我不明確含糊。我真的希望我可以放棄你的答案。 – RedCat23 2014-11-04 22:05:28

+0

@ RedCat23你還沒有足夠的代表upvote,但如果它是有用的(這也會給你一些代表點),請點擊勾來標記爲接受的答案。 – 2014-11-04 22:18:46

1

正如其他人所指出的,這可能不是一個好主意。但是,如果你想要做的只是遞增基類構造函數的計數器:

abstract class foo { 
    static int globalId = 0; 
    final int id; 
    foo() { 
     id = globalId; 
     ++globalId; 
    } 
} 

使用的AtomicInteger如果線程安全性是一個問題。

+0

如果我只增加基類中的計數器,那麼所有的子類將使用相同的'globalId'共享相同的ID生成。這不是我需要的。 – RedCat23 2014-11-04 21:52:07

+0

是的,所有人都會共享相同的身份證號碼,但每個班級將獲得唯一的身份證件。 globalId是靜態的,所以整個程序只有一個。您的問題表明您需要保證的是分配給每個實例的唯一編號,並且這樣做。這聽起來也許你的要求更具體:每個子類具有對子類**唯一**的整數,並且對於每個子類,整數開始和0並且沒有間隙。那是你需要的嗎? – 2014-11-04 21:54:41

+0

是的,這就是我需要的,每個子類的ID都是連續的。抱歉含糊不清。編輯的問題。 – RedCat23 2014-11-04 22:04:08

0

一種選擇,使用的UUID(http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html

UUID.randomUUID(); 

第二個選擇是隻使用的AtomicInteger此:

AtomicInteger idGen = new AtomicInteger(); 
    System.out.println(String.format("First is %d", idGen.getAndIncrement())); 
    System.out.println(String.format("Second is %d", idGen.getAndIncrement())); 

我不會用抽象類或繼承或者甚至是自定義類這個問題。

編輯:這是一個完整的示例,支持初始代碼。我不明白你怎麼能做出這樣簡單:的

public static class foo { 
    final public int id; 

    foo(int id) { this.id = id; } 
} 

public static class bar extends foo { 
    static final AtomicInteger idGen = new AtomicInteger(1); 

    public bar() { 
     super(idGen.getAndIncrement()); 
    } 
} 

public static class baz extends foo { 
    static final AtomicInteger idGen = new AtomicInteger(1); 

    public baz() { 
     super(idGen.getAndIncrement()); 
    } 
} 

public static void main(String[] args) { 
    bar b1 = new bar(); 
    baz b2 = new baz(); 
    bar b3 = new bar(); 

    System.out.println(String.format("b1.id = %d", b1.id)); 
    System.out.println(String.format("b2.id = %d", b2.id)); 
    System.out.println(String.format("b3.id = %d", b3.id)); 
} 
+0

UUID不必要的很長。使用'AtomicInteger'聽起來很理想,但我使用的是抽象類,因爲我需要重用這種行爲。 – RedCat23 2014-11-04 22:36:24

+0

如果您需要重用該行爲,請重用AtomicInteger實例。繼承是實現重用的可怕和不恰當的機制。 – clay 2014-11-04 23:10:08

+0

另外,當標準JDK具有完全符合您需要的類時,您確實不應創建新類。 – clay 2014-11-04 23:10:39