Reputation: 10376
I have a private inner class that encapsulates some functionality. It populates two ArrayLists. I have getters for the ArrayLists that just return the private variable. Are the getters needed? Can I just make the ArrayLists public instance variables? What's the best practice?
public class OuterClass {
//Stuff the OuterClass does
private class InnerClass {
private ArrayList<String> array1;
private ArrayList<String> array2;
public InnerClass() {
//Init and do stuff w/ arrays
}
public ArrayList<String> getArray1() {
return array1;
}
public ArrayList<String> getArray2() {
return array2;
}
}
}
Upvotes: 3
Views: 441
Reputation: 2674
Here is an approach that keeps the client from mucking about with the ArrayLists you provide through the getters. Note that the attempt to modify the ArrayList via the reference returned by the getter getResultsArray() is supposed to raise an exception:
package testCode;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
public class TestClass {
private ArrayList<String> resultsArray = Lists.newArrayList();
public void calculateResults(){
resultsArray.add("1");
resultsArray.add("2");
resultsArray.add("3");
}
public List<String> getResultsArray() {
return new ImmutableList.Builder<String>().addAll(resultsArray).build();
}
}
And a test driver:
package testCode;
public class TestMain {
public static void main(String[] args) {
TestClass testClass = new TestClass();
testClass.calculateResults();
for (String result : testClass.getResultsArray()) {
System.out.println(result);
}
try {
testClass.getResultsArray().add("fake result");
} catch (Exception e) {
System.out.println(e);
}
}
}
And the output:
1
2
3
java.lang.UnsupportedOperationException
The ImmutableList comes from Google's Guava library. In this case, an ImmutableList implements the List interface, but any method that would change the list immediately throws an UnsupportedOperationException. Note that because the ImmutableList can never change, the implemented code is very small, since anything in a normal List implementation that adjusts the list simply doesn't get written here. Very useful, and in this case, I am using it to implement defensive programming to prevent users of my TestClass from adjusting the test results I've returned to them.
Upvotes: 0
Reputation: 338
It's preferable to expose your API via Getters/Setters for encapsulation purposes, it's also good practice to declare your objects by interface types.
private List<E> list; // = new ArrayList<E>(); or initialize elsewhere
public List<E> getList() {
return list;
}
public void setList(List<E> list) {
this.list = list;
}
Upvotes: 0
Reputation: 30733
Assuming that the outer class (inside which the inner class is defined) isn't huge (like K lines of code) there's no point in defining getters.
Rationale:
The inner class is private. Getters will allow you to make (very limited) changes to the inner class without affecting the outer class. If the outer class is sufficiently small then the scope of code that is affected by changes that getters can prevent from leaking is also very small. Thus, there's no point in introducing them a-priori. If the need comes - introduce them, but till then - just stick with the simpler code.
Of course, if you'r refactoring the code and changing the inner class into a (standalone) top level class, then you need to introduce getters (or - even better - change the design to a tell-don't-ask scheme)
Upvotes: 0
Reputation: 38320
Best practice is to neither supply getters nor setters, instead your objects should not expose their implementation details.
Standard Java practice is to have private data members (a.k.a. fields) and to provide getters and setters.
Upvotes: 0
Reputation: 18143
The reason you wouldn't make the variables public is because you want to hide the implementation. What happens if you switch from an ArrayList to an actual array down the road? All your code would break. So you write to interfaces.
You may also want to avoid returning references to the array anyway, and rather provide methods to modify the array in ways that make sense for the class. Otherwise, it's possible for those using your class to make modifications that aren't expected by your class.
For instance:
Foo foo = new Foo();
List list = foo.getArray();
list.add( new Object() );
At this point, an object has been added to the content of your Foo object, and your foo object didn't get any chance to check the validity of that addition, to deny the addition, or to otherwise know it's there. If you had decided for performance reasons to delay creation of the array, you'd have been accessing a null. Boom.
Upvotes: 1
Reputation: 160261
Best practice is to supply getters. This avoids somebody setting the lists themselves, isolates users from underlying code changes, etc.
Whether or not they should be an unmodifiable list is a separate issue, and just depends.
Upvotes: 2
Reputation: 49197
Yes can make the Arraylist public, although best practice is to use getters. This allows you to build in side effects such as
It also lets you modify the internals of your class in the future without breaking the contract.
Upvotes: 2