2

I am speaking especially in regards to using a static variable to accomplish this. Consider the following object in Java:

public class MyObject{
    private static ArrayList<String> ID_List = new List<String>();
    private String ID_Number;
    public MyObject(){
        /* Assign a random number to ID_Number
         * And ensure that this is a unique number
         * not found in ID_List. Then add it to ID_List. */
    }

    /* Other methods and such */
}

To some degree, this is to ensure that each object made has a unique and distinguishing attribute that is easily accessible and readable. However, I am not sure if this kind of odd coupling between all objects of the same type is good practice.

Since it's making me uncomfortable I'm inclined to think that this isn't a good idea. What is the right way of thinking about this in an OOP manner?

May
  • 77
  • 1
  • 10
  • 1
    How would you handle the object `deletion`? Would it's ID be removed from the list? – MaxZoom Aug 17 '15 at 19:18
  • Would the contents of the ArrayList persist over multiple objects' creation or does each new object bring about a new (and empty) ID_List? – CubeJockey Aug 17 '15 at 19:19
  • 1
    I think you need a map of objects which will have a unique key for each object – Amit.rk3 Aug 17 '15 at 19:19
  • Does `MyObject` itself function properly without a unique ID? That is, is the ID only used by those who use `MyObject`s? – 5gon12eder Aug 17 '15 at 19:19
  • 1
    You might consider using [`UUID`](http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html). (That uses enough bits that the probability of a collision is just so preposterously low that it's not worth worrying about.) – Louis Wasserman Aug 17 '15 at 19:19
  • That's a good point MaxZoom and I totally forgot about that! You see, my preference for C++ made my mind totally not worry about things like that because "Oh, I'll just override the destructor." If I recall, Java has some sort of similar but not entirely equivalent thing called finalize()? Is there a way to implement that to deal with tidying up? Or is that also bad practice? – May Aug 17 '15 at 19:20
  • @5gon12eder : Although each object is mostly for the sake of performing some other computations, the objects themselves need to know about their IDs as well. – May Aug 17 '15 at 19:23
  • You probably want to extract this object management to a different class, that is responsible for creating, fetching, and deleting objects from an internally managed storage (similar to what you have but use a Map instead of a List as @Amit.rk3 mentioned above) – David Zech Aug 17 '15 at 19:25
  • @Amit.rk3 : Good idea. I may have a better solution to the problem! Which brings me to ask anyone: what is the process for answering my own question? Can I just answer normally like I'd answer any question? – May Aug 17 '15 at 19:26
  • @May Yes, you can (and are encouraged to) answer (and even accept) yourself. – 5gon12eder Aug 17 '15 at 19:29
  • @May I would never relay on the `finalize()` method to make in-house cleaning, as it would never be called in your program [lifespan](http://stackoverflow.com/a/2506525/4454454). If the only reason for that list to exist is to assure that `ID` field has unique value then I would go with `Psychrom`'s solution below. – MaxZoom Aug 17 '15 at 19:51
  • Indeed, I have actually already accepted Psychrom's solution since I found it to be the best and most simple! Thank you for the tip with finalize()! – May Aug 17 '15 at 19:56

5 Answers5

5

Wouldn't it be practical to use a static ID_INCREMENTOR and a local objectID? In constructor, add one to ID_INCREMENTOR, then set objectID to ID_INCREMENTOR current value?

Then no two objects would ever have the same id.

Example:

public class MyObject{
    private static long ID_INCREMENTOR = 0;
    private long id;
    public MyObject(){

          ID_INCREMENTOR++;
          id = ID_INCREMENTOR;

    }

public long getID(){
    return id;
}

/* Other methods and such */
}

This is perhaps the simplest way to do this, as far as I can see. The objects don't know about each other, though you can be assured that no two objects will ever have the same unique identifier, unless you set it through the class/reflection.

  • This works for my implementation! Great and simple, thanks! However, I have to ask if this is a known design pattern? – May Aug 17 '15 at 19:57
  • I don't know the name for what design pattern this is - if it is even a design pattern at all! :) If you absolutely need a "design pattern name," the only thing I can think of is the Composite Design pattern, which was more like your initial question. I would call this a Singlet design pattern, since it addresses the same issue without acknowledging 'subordinates' or other instances of the same class. The type is a cross between a singleton and a composite pattern. http://www.tutorialspoint.com/design_pattern/ And yes, I do agree on Long, MaxZoom. +1 and edited. :) –  Aug 17 '15 at 20:09
  • 1
    If this should be thread-save you should use AtomicLong for the ID_INCREMENTOR and call incrementAndGet() to get the long value for the id in the constructor. – Andreas Aug 17 '15 at 20:22
0

It depends on what you need it for.

Actually Java offers a similar mechanism with the hashCode() method that returns a hash code value for each instance of the object ( it may be unique per class, but that's not mandatory and you are responsible to compute it properly), although nobody keeps track of that id.

What you mention is totally possible and may be legit depending on your needs, in some other scenarios may be totally unnecessary and or even may cause memory leaks.

If you want to keep a list of the created object you may also have a "builder" class what maintains the list.

class MyObject {
     private static AtomicInteger count = new AtomicInteger();
     private int id;
     MyObject(){
         id = count.getAndIncrement();
     }
     public int hashCode() {
         return id;
     }
     public void equals(Object o) {
        return o instenceof MyObject && ((MyObject)o).id == this.id;
     }
}
class MyObjectBuilder {
    private static List<MyObject> instances = new ArrayList<>();
    public static MyObject createObject() {
         MyObject newOne = new MyObject();
         instances.add(newOne);
         return newOne;
     }
 }

Other option is to use a Map, or a Set but again, depend on what you need it for.

You can also read more about equals and hashcode in here

Community
  • 1
  • 1
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • This seems like a wonderful idea and may be better than an alternate solution I was considering! Thanks! – May Aug 17 '15 at 19:28
  • hashCode is not unique. http://eclipsesource.com/blogs/2012/09/04/the-3-things-you-should-know-about-hashcode/ http://stackoverflow.com/questions/21368492/using-hashcode-for-a-unique-id https://www.daniweb.com/software-development/java/threads/283972/is-an-objects-hash-code-unique Plenty more. I don't mean to be that guy, but it's simply not true. –  Aug 17 '15 at 19:36
0

Why to do all that, when you have that object.hashcode() returns a unique object ID for it almost all the time? It is very unlikely to have the same hashcode for different instances of the same object though the contract between equals() and hashcode() does not impose on guarantee of different hashcode when the objects are not equal. Moreover, I still didn't like the way of having a static ArrayList maintained for that in the class itself for that housekeeping. Even if you need such thing, externalize that ArrayList from this class. Let the management of unique instances of this object be done by a different class. Remember the Single Responsibility Principle in SOLID principles of OOPs.

Thomas Mathew
  • 389
  • 2
  • 8
0

This isn't that weird. You can find a similar pattern in Effective Java. Here is some of that info http://www.informit.com/articles/article.aspx?p=1216151

As it suggests, I would probably go for a factory method to get these objects, instead of newing them each time.

Carlos Bribiescas
  • 4,197
  • 9
  • 35
  • 66
0

I am posting my own idea for a solution here in the case that someone looking at this might think my approach is more suitable to their needs. However, I'll be accepting PsyChrom's answer since I believe it is the best.

Assuming that the objects need to know their own ID number at all times, and may from time to time know what the ID numbers of other objects in memory are, consider the following implementation:

public class MyObject{
    private String ID_Number;
    public MyObject(String ID){
        this.ID_Number = ID;
    }

    public getID(){
        return ID_Number;
    }

    public checkUniques(List<String> ID_List){
        /* Do what not */
    }
    /* Other methods and such */
}

Assuming you only have one area where you are generating these objects, then simply do the following:

ArrayList<String> ID_List = new List<String>();
/* Create a number/string before you make the object
 * Which is unique. */
MyObject newObj = new MyObject(someUniqueStr);

In my own implementation, I actually only need the objects to know about the ID numbers of objects of their own type rarely. As a result, perhaps just adding in a method for it may be satisfactory instead of providing them with their own list. This way we externalize the housekeeping on our objects like a user previous suggested!

May
  • 77
  • 1
  • 10