Domanda

I encountered a problem while dealing with a call of a static method in another class.

So I have a function which is like follow, where I need to extract two values, a counter and an object :

public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, DBObject result) {
        int mergeCount = 1;
        if (!cursorMap.isEmpty()) {
            long ealiest = Long.MAX_VALUE;
            for (DBObject o : cursorMap.keySet()) {
                // do stuff to init tmp
                ...
                if (tmp < ealiest) {
                    result = o;
                    ealiest = tmp;
                }
            // other stuff .....
        }
        return mergeCount;
    }

here is how I call it in my other class :

DBObject result= null;
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result);

I checked in debug mod and result is set in getEarliestValue but when it's go out of the function call result is still null. I thought that references where like pointers with the difference that we couldn't do arithmetic operation on the reference itself, but with this behavior it seems that even if we change the pointed value it still only in the local scope.

The only idea that I found was to put it in a List but this is neither elegant nor optimal.

Any suggestion ? Thanks in advance.

È stato utile?

Soluzione

Passing result here is the same thing as passing null. You have to return this DBObject someway. For example, you can return something like Map.Entry<Integer, DBObject>. This could not be supposed to be a good solution, maybe you should create some class like BlahBlahResult, containing both int result and DBObject.

If you really-really want to pass it as a parameter, you may pass something like AtomicReference<DBObject> and set it inside the method:

public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, AtomicReference<DBObject> result) {
    int mergeCount = 1;
    if (!cursorMap.isEmpty()) {
        long ealiest = Long.MAX_VALUE;
        for (DBObject o : cursorMap.keySet()) {
            // do stuff to init tmp
            ...
            if (tmp < ealiest) {
                result.set(o);
                ealiest = tmp;
            }
        // other stuff .....
    }
    return mergeCount;
}

...
...

AtomicReference<DBObject> resultReference = new AtomicReference<>(null);
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, resultReference);
DBObject result = resultReference.get();

Altri suggerimenti

In java "References to Objects are passed by value".

DBObject result= null;
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result); // here result --> null i.e, points to nothing

public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, DBObject result) {
        int mergeCount = 1;
        if (!cursorMap.isEmpty()) {
            long ealiest = Long.MAX_VALUE;
            for (DBObject o : cursorMap.keySet()) {
                // do stuff to init tmp
                ...
                if (tmp < ealiest) {
                    result = o;  // here (new)result --> o . (original)result-->null
                    ealiest = tmp;
                }
            // other stuff .....
        }
        return mergeCount;
    }

the result parameter is a pointer. Java does not support pointer-to-pointer as in c/c++.

you can use a class contains a DBObject field, then pass this class to the method.

class Dummy {
    DBObject result;
}

modify your getEarliestValue method, replace the argument DBObject result with Dummy dummy,

public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, Dummy dummy)

and then replace code result = o with dummy.result = o

Dummy dummy = new Dummy();
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, dummy);
DBObject result = dummy.result;

this is a simulation of **ptr in c/c++

You can do the following:

    DBObject result= new DBOBject() // or any initializing code;
    /** don't try to change or re-initialize reference inside the method
        because the result will still point to old one
    */
    int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result); 
    // use the result reference.

This is not specific for java also in the C++ or C pointer unless you use the & with pointer reference.

Note that it seems that the method cann't run alone with out DBObject instance so I think this method should be an instance method of Class DBObject and not a Util method,

For example:

int mergeCount = result.getEarliestValue(cursorList);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top