0

Code A works well, I think Code B can work correctly, but in fact, Code B doesn't work correctly. Why?

Why can't I create an object in the function- private void SetField(Context mContext,MAtt aField,String name) ?

Code A

public class MURLPar {

    public MAtt diskcount=new  MAtt();
    public MAtt diskindex=new  MAtt();


    public MURLPar(Context mContext){
        SetField(mContext,diskcount,"Pardiskcount");
        SetField(mContext,diskindex,"Pardiskindex");
    }


    public class MAtt {
        public String name;
        public String value;
    }


    private void SetField(Context mContext,MAtt aField,String name){
        int id = mContext.getResources().getIdentifier(name, "string", mContext.getPackageName());
        aField.name=mContext.getString(id);
    }
}

Code B

public class MURLPar {

    public MAtt diskcount; 
    public MAtt diskindex;


    public MURLPar(Context mContext){
        SetField(mContext,diskcount,"Pardiskcount");
        SetField(mContext,diskindex,"Pardiskindex");
    }


    public class MAtt {
        public String name;
        public String value;
    }


    private void SetField(Context mContext,MAtt aField,String name){
        aField=new MAtt(); //Create object
        int id = mContext.getResources().getIdentifier(name, "string", mContext.getPackageName());
        aField.name=mContext.getString(id);
    }
}
zohar
  • 15
  • 8
HelloCW
  • 843
  • 22
  • 125
  • 310

2 Answers2

4

Because aField gets new memory address when you use the command aField=new MAtt();

As a result memory address of diskcount and diskindex remain uninitialized.

For more check here: https://stackoverflow.com/a/73021/3923800

Community
  • 1
  • 1
xro7
  • 729
  • 6
  • 27
2

What's happening in code B is that the MURLPar constructor passes a reference to diskcount/diskindex to SetField, which within that method has the name aField.

You then reassign aField with a reference to a newly created object, and you then manipulate that object. Note that aField is now referring to a completely separate object, and not whatever it was referring to when you entered SetField.

If you're familiar with C you can think of what you're doing here as something along these lines:

void SetField(MAtt *aField) {
    aField = (MAtt*) calloc(1, sizeof(MAtt));
}

MAtt *diskcount;
SetField(diskcount);

And then expecting diskcount to have changed after the call to SetField, which it obviously won't have.


If you want something like an out parameter, you can simulate that by returning a newly created object:

private MAtt SetField(Context mContext, String name){
    MAtt aField = new MAtt(); //Create object
    int id = mContext.getResources().getIdentifier(name, "string", mContext.getPackageName());
    aField.name=mContext.getString(id);
    return aField;
}

And then:

diskcount = SetField(mContext, "Pardiskcount");
Michael
  • 57,169
  • 9
  • 80
  • 125