2014-11-04 42 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