Java create a unique ID for each instantiated object using instance methods instead of class/static methods
Asked Answered
H

4

11

Quite new to this so I hope I have the terminology in the title right.

I am trying to figure out how to create an instance method that will do the following:

--An ID number is returned.

--As each object is created from the class constructor(instantiated?), a unique integer ID number is assigned to it. The first ID number is 1, and as new objects are instantiated, successive numbers will be assigned.

I am able to find examples of class/static methods that do the above however I am unable to figure out how to do this with an instance method. My attempt is below:

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;
    }

}

My main method is as follows:

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());


    }
}

Please note I have not included my entire code for the sake of simplicity and easiness to follow. I hope I have added enough.

I also don't want to use java.util.UUID.

Hamel answered 17/2, 2016 at 15:58 Comment(1)
You need a static id generator and an instance id field for the current instance.Diary
A
10

The problem right now is that your 'id' is an instance variable, meaning it belong to the objects you create. Think of it that every time you create an object a new and fresh copy of your instance variable is made. So every time you create an object the id is first set to 0, then post incremented once (thus all objects have an id=0).

If you want to create a variable that, say, automatically counts all objects you have created in a class or has the id, you need to make a class variable. These variable belong to all the objects you create from a class and the keyword used for that is 'static'.

Note: I have used a static variable BUT not a static method. If you don't want to use static at all, it is a different question

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;
}

}

A simple change of keyword will make your program correct. You dont have to do too much complicated stuff.

It is difficult to grasp the concept of class and objects, static and instance variables at first. Let me know if you'd like more explanation :)

Aquarium answered 17/2, 2016 at 17:18 Comment(3)
Excellent easy to follow example. The one change I made was id=++count, so that when an objected is instantiated, the value of count will change to 1 AND THEN be assigned to pointID. This would make it so that the id would start from 1 instead of 0Hamel
How we could achieve this without static at all?Lyrist
@AashishKumar See below answer https://mcmap.net/q/984561/-java-create-a-unique-id-for-each-instantiated-object-using-instance-methods-instead-of-class-static-methodsAquarium
T
4

In the context of your current code, the simplest thing to to do is as below:

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;
    }
}

Test

public class Test {

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

Output

1000 1001 1002 1003 1004 1005 1006 1007 1008 1009

Tolu answered 17/2, 2016 at 16:54 Comment(0)
W
3

Maintaining an ID sequence is a separate responsibility from the rest of what your object does, and doesn't belong to any one instance of the Coordinates class, so it belongs in a different object. Make a separate object to maintain the sequence and hand out numbers, something like

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

then use that sequence to initialize your objects:

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

By the way keeping user input separate from the model makes things simpler, you may want to instantiate your Coordinates class in cases where the input doesn't come from the user. Console input doesn't go in a constructor. You might have a Coordinate class like

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 + ")";
    }
}

and a main method like

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());
    }
}
Waterresistant answered 17/2, 2016 at 16:12 Comment(5)
This is a bit hard for someone like me to follow. Could you expand your code to explain AtomicLong, and getNextValue. Also, where does console input go then? In the main method right before an object is instantiated?Hamel
@SajSeesSound: AtomicLong is here: docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/…, it just wraps a value and allows updates atomically. And yes, the main method would be a good place to do your console input.Waterresistant
You could use an LongAdder instead of AtomicLong if multi-threading and high performance are important. blog.palominolabs.com/2014/02/10/…Hadleigh
@Jochen: there is no indication that multithreading is relevant here. I used AtomicLong here because it's easy and I didn't want to overthink a toy example (while still shutting down nitpickers who would complain about using ++ or +=).Waterresistant
@JochenBedersdorfer 10 years later, your comment is invaluable. Thank you!!!Helmick
C
0

You can either make that ID static, or you could just make a Parent class called "Coordinate" (with that ID again being static) with "Point" children, and increment the ID in the constructor of each "Point" object.

Static would seem like the way to go.

Clique answered 17/2, 2016 at 16:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.