Java – return a object without returning the reference

javaobject-orientedobject-oriented-design

i'm having some trouble with returning objects and lists of objects. To problem is I want to return a object in my example an developer but I don't want to give the reference.
What's the best approach for this? First i thought just returning a new Developer:

public Developer getDeveloper(int index){
    Developer d =  developers.get(index);
    return new Developer(d.getName());
}

But this looks good for simple objects but what if i have a developper object that has a instance field that is also a object or a list?

An other question is about lists i return a list of developers:

public List<Developer> getDeveloppers(){
    return Collections.unmodifiableList(this.developers);
}

So the list is now non modifiable but I think the objects are not… how can i return a list with unmodifiable objects?

The example code:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Project {

    private List<Developer> developers;
    private String name;

    public Project(){
        this("DEFAULT");
    }

    public Project(String name){
        this.setName(name);
        this.developers = new ArrayList<Developer>();
    }

    public List<Developer> getDeveloppers(){
        return Collections.unmodifiableList(this.developers);
    }

    public Developer getDeveloper(int index){
        Developer d =  developers.get(index);
        return new Developer(d.getName());
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }   
}

The developer class, note this one has no instance object:

public class Developer {

    private String name;

    public Developer(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }
}

Help would be appreciated! Regards

Best Answer

You can make the objects immutable:

public class Developer {

    private final String name;

    public Developer(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

}

Then there will be no issue with returning the reference.

Otherwise you can map each developer to a unmodifiable view of itself:

public Stream<IDeveloper> getDeveloppers(){
    return this.developers.map(dev => dev.unmoddifiableView());
}

Where unmoddifiableView() returns an instance of IDeveloper that doesn't allow changes:

private static IDeveloper readOnlyView = new UnmodifiableDeveloper(this);

public IDeveloper unmoddifiableView(){
    return readOnlyView;
}

And UnmodifiableDeveloper delegates all getters to the constructor parameter.