【问题标题】:Java create a unique ID for each instantiated object using instance methods instead of class/static methodsJava 使用实例方法而不是类/静态方法为每个实例化对象创建一个唯一 ID
【发布时间】:2016-05-29 10:47:08
【问题描述】:

对此很陌生,所以我希望标题中的术语正确。

我正在尝试弄清楚如何创建一个 实例方法,它将执行以下操作:

--返回一个ID号。

--由于每个对象都是从类构造函数(实例化?)创建的,因此为其分配了一个唯一的整数 ID 号。第一个 ID 编号为 1,当实例化新对象时,将分配连续的编号。

我能够找到执行上述操作的类/静态方法的示例,但是我无法弄清楚如何使用实例方法来执行此操作。我的尝试如下:

class Coordinates
{
    private int iD = 0;
    private float xCoordinate;
    private float yCoordinate;

    public Coordinates()
    {
        //Asks for input and assigns it to the two variables below
        Scanner keyboard = new Scanner(System.in);
        System.out.println("Please enter the X Coordinate followed by the return key");
        xCoordinate = keyboard.nextDouble();
        System.out.println("Please enter the Y Coordinate followed by the return key");
        yCoordinate = keyboard.nextDouble();

        iD++;
    }

    public getiD()
    {
        return iD;
    }

}

我的主要方法如下:

public class Machine
{
    public static void main(String[] args)
    {
        Coordinates c1 = new Coordiantes();
        Coordinates c2 = new Coordiantes();
        Coordinates c3 = new Coordiantes();

        System.out.println("ID: " + c1.getID());
        System.out.println("ID: " + c2.getID());
        System.out.println("ID: " + c3.getID());


    }
}

请注意,为了简单和易于理解,我没有包含我的整个代码。我希望我已经添加了足够多的内容。

我也不想使用 java.util.UUID。

【问题讨论】:

  • 您需要一个 static id generator 和一个用于当前实例的实例 id 字段。

标签: java static increment uniqueidentifier instance-methods


【解决方案1】:

现在的问题是您的“id”是一个实例变量,这意味着它属于您创建的对象。 想一想,每次创建对象时,都会创建实例变量的新副本。 因此,每次创建对象时,id 首先设置为 0,然后 post 递增一次(因此所有对象的 id=0)。

如果你想创建一个变量,比如说,自动计算你在一个类中创建的所有对象或有 id,你需要创建一个类变量。 这些变量属于您从一个类创建的所有对象,用于该类的关键字是“静态”。

注意:我使用的是静态变量,但不是静态方法。如果您根本不想使用静态,这是一个不同的问题

class Coordinates
{
private static int count = 0;
private int id=0;
private float xCoordinate;
private float yCoordinate;

public Coordinates()
{
    //Asks for input and assigns it to the two variables below
    Scanner keyboard = new Scanner(System.in);
    System.out.println("Please enter the X Coordinate followed by the return key");
    xCoordinate = keyboard.nextDouble();
    System.out.println("Please enter the Y Coordinate followed by the return key");
    yCoordinate = keyboard.nextDouble();

    id=count++;
}

public getiD()
{
    return iD;
}

}

关键字的简单更改将使您的程序正确。你不必做太多复杂的事情。

一开始很难掌握类和对象、静态变量和实例变量的概念。如果您需要更多解释,请告诉我:)

【讨论】:

  • 优秀的易于遵循的例子。我所做的一项更改是 id=++count,因此当实例化对象时,count 的值将更改为 1,然后分配给 pointID。这将使 id 从 1 而不是 0 开始
  • 我们如何在没有静态的情况下实现这一点?
  • @AashishKumar 请参阅下面的答案stackoverflow.com/a/35461985/5930693
【解决方案2】:

在您当前代码的上下文中,最简单的做法如下:

import java.util.concurrent.atomic.AtomicInteger;

public class Coordinates {

    //static id generator shared among all instances of Coordinates 
    private static final AtomicInteger idGenerator = new AtomicInteger(1000);

    private final Integer id;

    public Coordinates() {
        //assign unique id to an instance variable
        id = idGenerator.getAndIncrement();
    }

    public int getId() {
        //return instance variable
        return id;
    }
}

测试

public class Test {

    public static void main(String[] args) {
        for(int i = 0; i < 10; ++ i){
            System.out.println(new CoordinatePoint().getId());
        }
    }
}

输出

1000 1001 1002 1003 1004 1005 1006 1007 1008 1009

【讨论】:

    【解决方案3】:

    维护 ID 序列是与对象的其他工作分开的职责,并且不属于 Coordinates 类的任何一个实例,因此它属于不同的对象。制作一个单独的对象来维护序列并分发数字,例如

    public class MySequence {
        private AtomicLong currentValue = new AtomicLong(0L);
        public long getNextValue() {
            return currentValue.getAndIncrement();
        }
    }
    

    然后使用该序列来初始化您的对象:

    new CoordinatePair(mySequence.getNextValue(), x, y);
    

    通过将用户输入与模型分开使事情变得更简单的方式,您可能希望在输入不是来自用户的情况下实例化您的 Coordinates 类。控制台输入不会进入构造函数。你可能有一个像

    这样的坐标类
    public CoordinatePoint {
        private long id;
        private float x;
        private float y;
        public CoordinatePoint(long id, float x, float y) {
            this.id = id;
            this.x = x;
            this.y = y;
        }
        public String toString() {
            return "id=" + id + ", (" + x + ", " + y + ")";
        }
    }
    

    还有一个主要的方法,比如

    public class Example {
    
        public static void main(String ... args) {
            MySequence seq = new MySequence();
            Scanner keyboard = new Scanner(System.in);
            System.out.println("Please enter the X Coordinate followed by the return key");
            float xCoordinate = keyboard.nextDouble();
            System.out.println("Please enter the Y Coordinate followed by the return key");
            float yCoordinate = keyboard.nextDouble();
            CoordinatePoint c1 = new CoordinatePoint(seq.getNextValue(), xCoordinate, yCoordinate);
            System.out.println(c1.toString());
        }
    }
    

    【讨论】:

    • 这对于像我这样的人来说有点难以理解。您能否扩展您的代码来解释 AtomicLong 和 getNextValue。另外,控制台输入到哪里去呢?在实例化对象之前的 main 方法中?
    • @SajSeesSound:AtomicLong 在这里:docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/…,它只是包装一个值并允许自动更新。是的,main 方法是进行控制台输入的好地方。
    • 如果多线程和高性能很重要,您可以使用LongAdder 而不是AtomicLongblog.palominolabs.com/2014/02/10/…
    • @Jochen:没有迹象表明多线程在这里是相关的。我在这里使用 AtomicLong 是因为它很简单,而且我不想过多考虑玩具示例(同时仍然关闭会抱怨使用 ++ 或 += 的挑剔者)。
    【解决方案4】:

    您可以将该 ID 设为静态,也可以只使用“Point”子级创建一个名为“Coordinate”的父类(该 ID 再次为静态),并在每个“Point”对象的构造函数中递增 ID .

    静态似乎是要走的路。

    【讨论】:

      猜你喜欢
      • 2017-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      • 2013-09-11
      相关资源
      最近更新 更多