HelloCW HelloCW - 4 months ago 11
Java Question

Why can't I create a object in a function in Java?

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

Answer

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