My question is regarding declaring an arraylist as final. I know that once I write final ArrayList list = new ArrayList(); I can add, delete objects from this list, but I can not list = new ArrayList() or list = list1. But what will be the use of declaring arraylist as
Private static final ArrayList list = new ArrayList();. And apart from the difference I have mentioned above what will be the difference between following two declaration:
1. ArrayList list = new ArrayList()
2. private static final ArrayList list = new ArrayList();
Just to "bring a little water to your Mill" you will understand the interest of final when you'll want to make your list publically availiable but unmodifiable.
In java one can make a list unmodifiable with Collections.unmodifiableList(modifiableList).
Now have a look to the following code :
public class MyClass{
public static List<String> MY_PUBLIC_LIST;
static{
ArrayList<String> tmp = new ArrayList<String>();
tmp.add("a");
tmp.add("b");
tmp.add("c");
MY_PUBLIC_LIST = tmp;
}
}
Well, in anyclass, anywhere in your code you can do something like this
MyClass.MY_PUBLIC_LIST = null;
MyClass.MY_PUBLIC_LIST = new ArrayList<String>();
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
When you add the final keyword to your variable, the first two won't be allowed
public static final List<String> MY_PUBLIC_LIST;
But you'll still be able to modify the content of the list :
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
By adding a Collections.unmodifiableList(modifiableList) at the end of the static block you'll prevent this too :
MY_PUBLIC_LIST = Collections.unmodifiableList(tmp);
Ok we are almost there. Just to be sure you get the whole picture lets keep the Collections.unmodifiableList(modifiableList) but let me remove the final modifier
public class MyClass{
public static List<String> MY_PUBLIC_LIST;
static{
ArrayList<String> tmp = new ArrayList<String>();
tmp.add("a");
tmp.add("b");
tmp.add("c");
MY_PUBLIC_LIST = Collections.unmodifiableList(tmp);
}
}
What can you do in that case ?
...
...
Well you can do whatever you want like in the first case (given that you assign the new list first) :
MyClass.MY_PUBLIC_LIST = null;
MyClass.MY_PUBLIC_LIST = new ArrayList<String>();
MyClass.MY_PUBLIC_LIST.clear();
MyClass.MY_PUBLIC_LIST.add("1");
You're right that declaring the list final means that you cannot reassign the list variable to another object.
The other question (I think) was
public class SomeClass {
private static final ArrayList list = new ArrayList();
}
vs
public class SomeClass {
ArrayList list = new ArrayList();
}
let's take each modifier in turn.
private Means only this class (SomeClass) can access list
static Means that there is only one instance of the list variable for all instances of SomeClass to share. The list instance is associated with the SomeClass class rather than each new SomeClass instance. If a variable is non-static it's said to be an instance variable
final as you know means that you cannot reassign the list variable another value.
In the second declaration there are no modifiers, so the variable is an instance variable and it also gets package-private access protection (Sometimes called default access protection). This means that this class (SomeClass) and other classes in the same package can access the variable.
You can find out more about public, private, and package-private here: Access control
You can find out more about final and static here: Class variables
When you say
final ArrayList list = new ArrayList();
this means that the variable list will always point to the same ArrayList object. There are two situations in which this can be useful.
You want to make sure that no-one reassigns your list variable once it has received its value. This can reduce complexity and helps in understanding the semantics of your class/method. In this case you are usually better off by using good naming conventions and reducing method length (the class/method is already too complex to be easily understood).
When using inner classes you need to declare variables as final in an enclosing scope so that you can access them in the inner class. This way, Java can copy your final variable into the inner class object (it will never change its value) and the inner class object does not need to worry what happens to the outer class object while the inner class object is alive and needs to access the value of that variable.
The second part of your question is about the difference between
ArrayList list = new ArrayList();
and
private static final ArrayList list = new ArrayList();
The difference of course are the modifiers. private means not visible outside the class, static means that it is defined on the class level and doesn't need an instance to exist, and final is discussed above. No modifiers means package-private or default access.
You say "I can add, delete (and find) objects", but who is I?
The different between your two cases concerns from which code those list operations can be called.
In general you need to consider the scope of the declaration, you greatly increase the maintainability of code if you reduce the visibility of your variables. If you have a class:
Public Class MyThing {
public int importantValue;
// more code
}
That important value can be changed by any other code, anywhere else in an application. If instead you make it private and provide a read accessor:
Public Class MyThing {
private int importantValue;
public int getImportantValue(){
return importantValue;
}
// more code
}
you now know only the class itself can change the value - for large applications this massively increases maintainability. So declaring the list private limits what code can see, and change the contents of the list.
The use of static makes the list shared by all instances of the class, rather than each instance getting its ovn copy.
Related
I have Singleton class like this:
public class Singleton
private static Singleton instance;
private ArrayList<Release> releases;
private ArrayList<Place> places;
ArrayList<ArrayList<Object>> list = new ArrayList<ArrayList<Object>>(2);
private Singleton() {
releases = new ArrayList<Release>();
places = new ArrayList<Place>();
list.add(release); //error, required AL<Object>, provided AL<Release>
list.add(places); //same
}
public static Singleton getInstance(){
/* Singleton code */
}
I thought that it is possible because, every Class extends Object class. My intention is to read from files where ALs are saved as object a then these ALs have in collection of one AL, where al.get(PLACES_INDEX) would return places and so on. It is a good approach or am I missing something?
Later on I would like to have some unified method, which would be something like:
public ArrayList<T> getArrayList() {
/*return places or releases based on <T>*/
}
I don't know if it's even possible since this class is Singleton.
I will explain why you're getting the error, but from what you describe this looks like a bad design for your class: don't store "generic" lists in a list, to access them based on a certain index. And don't create a method like public ArrayList<T> getArrayList() { that returns one of the lists depending on the type T. This is overengineering, and makes your code much harder to maintain, and easy to break.
Just keep the distinct lists separately, and provide getters for each one of them. If you are reading from a file and want to deserialize the content into a data structure, simply create a class structure that models the content. Your code will be much simpler and easier to read.
Even though Release is a subclass of Object, ArrayList<Release> is not a subclass of ArrayList<Object>, therefore you cannot add an ArrayList<Release> to an ArrayList<ArrayList<Object>> (we say that generics are not covariant). If Java allowed you to do that, then you can end up with a scenario that breaks generic usage of the code:
ArrayList<ArrayList<Object>> list = new ArrayList<>();
ArrayList<Release> releases = new ArrayList<>();
list.add(releases); // imagine this is allowed
ArrayList<Object> releasesFromList = list.get(0);
releasesFromList.add(place); // oops, added a place to list of release
In a Java class where you normally declare/define instance variables, I would like to have an ArrayList as one of the instance variables and initialize it with some elements to start out with. One way of doing this is declare the ArrayList and initialize it in a constructor. However, I am wondering why it is illegal to initialize the value outside the constructor. For example,
public class Test {
// some instance variables...
private ArrayList<String> list = new ArrayList<String>();
list.add("asdf");
// methods here...
}
So I get that this is illegal. But why exactly is this illegal?
You cannot execute statements freely in a class. They should be inside a method. I recommend you to add this line in the constructor of the class or in a class initialization block.
In class constructor:
public class Test {
// some instance variables...
private List<String> list = new ArrayList<>();
public Test() {
list.add("asdf");
}
// methods here...
}
In class initialization block:
public class Test {
// some instance variables...
private List<String> list = new ArrayList<>();
{
list.add("asdf");
}
// methods here...
}
More info:
What's the difference between an instance initializer and a constructor?
It is illegal, because initializing fields is exactly the reason, why constructors exist!
In Java, it is not possible to have code anywhere 'outside' of a method or constructor (or class-initializer). It is possible to have simple expressions in a field initializer, but not multiple statements:
public class Test {
// here, at class level, you can only declare fields, methods or constructors!
// But you cannot have procedural code!!!
// field without initializer (=> default initialization with null)
private List<String> list1;
// field with explicit initializer expression
private List<String> list2 = new ArrayList<String>();
public Test() {
// initialize fields
this.list1 = new ArrayList<>();
this.list2.add("asdf");
}
}
If you use Guava (https://code.google.com/p/guava-libraries/) you will have this sugar code available:
private ArrayList<String> list = Lists.newArrayList("element1", "element2", ...)
Also, has was mentioned before, I suggest not typing your field as ArrayList but as List. Always use the more abstract type, good rule of the thumb.
That code will not get called if it outside a defined function for the class. If this were to be allowed, everything within the class would get executed as soon as you created a class which is not a behavior one would want.
If you would like to initialize with some elements, you can do it like this:
private ArrayList<String> list = new ArrayList<>(java.util.Arrays.asList("asdf"));
You cannot do what you're proposing, instead you can initialize the variable using java.utils.Arrays.asList(T) like this:
public class Test{
private List<String> foo = new ArrayLis<>(Arrays.asList("a", "b", "c"));
}
Recently on the interview I had an interesting question.
We have mutable class:
final class Example {
private int i;
private String s;
private Object o;
// get, set
}
And instance of this class Example e = new Example();
Can we somehow make this instance immutable? Without changing original class.
My thoughts:
Deep cloning of this instance? But not sure if it's possible.
Maybe something like serialization/deserialization?
If you are unable to make modifications to the Example class and you cannot subclass it (in your snippet, it is marked as final) the closest solution I can think of is to create a wrapper class, which is immutable. This is not a perfect solution, and has it's drawbacks.
First, how to do it:
final class ImmutableExample {
// Redeclare every field as in the Example class
// but make sure they can't be reassigned
// (in this case I'll declare them as final)
private final int i;
private final String s;
private final Object o;
ImmutableExample(Example mutableExample) {
// copy fields from original
this.i = mutableExample.getI();
this.s = mutableExample.getS();
this.o = mutableExample.getO();
}
// add getters but definitely no setters
}
Then everywhere you have code like this:
Example e = new Example();
e.setI(42); // etc
Change to:
Example e = new Example();
e.setI(42); // etc
ImmutableExample immutableE = new ImmutableExample(e);
And pass around references to immutableE, and make sure that the e reference does not escape.
Now, for the drawbacks:
ImmutableExample is not an instance of Example, so you cannot pass the immutable type to a method which expects the mutable type, and operations like if (immutableE instanceof Example) or (Example)immutableE will not work as before
You have to be very careful that every field of Example is also immutable, or ImmutableExample will also be mutable. Consider, for example, that the field of type Object could be something mutable, like a HashMap or a Date.
When the Example class changes, you have to repeat the change in ImmutableExample.
If it was possible to subclass Example, or if it was an interface, this approach might be more useful, but I can't see any other way when Example cannot be subclassed.
If each of those fields have getters/setters, then to make it immutable, you will have to
Make each field private and final
Make a copy of each field when it's getter is called
Remove all setters
Any methods within the class that changes it's state must either be removed or use the new getters to access any internals
Immutability is a property of a class not an instance. So besides bytecode twiddling or other means to change the class; not possible.
With a none final class i would create an immutable decorator. That would not make the instance immutable, but provide an immutable wrapper to that instance.
You could not assign the instance to any variable/field, making it impossible to change it ;)
I have the following, stripped-down Java code:
// Class, in it's own file
import java.util.*;
public class Superclass {
protected List<Subclass> instances = new ArrayList<>();
public class Subclass extends Superclass {
private int someField;
public Subclass(int someValue) {
this.someField = someValue;
updateSuperclass();
}
private void updateSuperclass() {
super.instances.add(this);
}
}
}
// Implementation, somewhere else, everything has been imported properly
Superclass big = new Superclass();
Subclass little1 = big.new Subclass(1);
Subclass little2 = big.new Subclass(2);
Subclass little3 = big.new Subclass(3);
I want to implement a method in Superclass to do something with all the Subclasses. When a Subclass is created, it should add itself to a list in Superclass, but whenever I try to loop through that list in Superclass, it says the size is 1. The first element in the list (instances.get(0)) just spits out a String with all the proper information, but not in object form, and not separately. It's like every time I go to add to the list, it gets appended to the first (or zeroeth) element in String form.
How can I solve this so I can maintain an ArrayList of Subclasses to later loop over and run methods from? I'm definitely a beginner at Java, which doesn't help my case.
If all you need is a count then I suggest a static value that is updated in the constructor of the parent class.
private static int instanceCount = 0;
public Constructor() {
instanceCount++;
}
If you absolutely need every instance in a list so you can do something with them then I recommend you strongly re-consider your design.
You can always create a utility class that will let you maintain the list of objects to run processes on. It's more "Object Oriented" that way. You can also create one class that has all of the operations and then a simpler bean class that has only the data values.
But, if you insist, you can still use the same technique.
private static List<SuperClass> list = new LinkedList<SuperClass>;
public Constructor() {
list.add(this)
}
Each instance gets its own copy of your superclass's variables.
What you want to do is make the variable "static" by putting the static keyword before it. You probably don't even need the superclass accomplish what you're trying to do.
I have a class and this class has one public element ArrayList myList.(I have other elements too in my class but they have nothing to do with this element)
What I am trying to do is having different ArrayLists for different Class Objects. However when I tried to code this, even if I use different class objects, the code reserves every entry in one single ArrayList. What am i doing wrong?
This is what i tried:
My class:
public class myClass {
public static ArrayList myList;
public static ArrayList getList() {
return myList;
}
public static void setList(ArrayList myList) {
myClass.myList = myList;
}
In main:
myClass my = new myClass();
myClass my2 = new myClass();
ArrayList tmp = new ArrayList();
ArrayList tmp2 = new ArrayList();
tmp.add("aaaaa");
tmp.add("bbbbb");
tmp2.add("ccccc");
tmp2.add("ddddd");
my.setList(tmp);
my2.setList(tmp2);
for(int i=0;i<my.getList().size();i++)
{
System.out.println(my.getList().get(i));
}
And the output of this main is being:
ccccc
ddddd
but i want it to be:
aaaaa
bbbbb
What am i doing wrong?
You declared myClass#myList static, which means only one instance of myList will exist, inside the CLASS myClass. Declare it non-static, including the getter and setter, to have different instances for my and my2 and you're good to go.
you are using static in your class.
remove static keyword for the variable in your class and you should be fine. Static is class scoped so will be shared across objects.
As identified by the other comments, you are declaring the ArrayList as static, which means it is shared across all object instances of the class - as such in the following statement:
my.setList(tmp);
my2.setList(tmp2);
...the second setList overwrites the first.
Read on up the Singleton pattern for a good example of where to use static fields:
Singleton pattern
As an aside, consider passing your values into the constructor and only providing a getter, thus encapsulating the use of ArrayList and making the values immutable - for example:
myClass my = new myClass("aaaa", "bbbb");
String element = my.get(0);
Finally, if using Java 5 or 6, think about using Generics when working with collections/lists:
List<String> tmp = new ArrayList<String>();
Hope that helps.
Modify your class as follows
public class myClass {
public ArrayList myList;
public ArrayList getList() {
return myList;
}
public void setList(ArrayList myList) {
listler.myList = myList;
}
You're using static ArrayList myList which is common to all the objects of your class myClass. Therefore, you're not getting what you expect. Avoid using static, if you need to use the ArrayList myList separately to all the objects of the class.
Java allows you to access static members of a class in both the ways with its objects and with associating them with their class name but its a bad practice to associate static members with the class objects.
Associating static members themselves with the class object was actual a flaw in language design itself (hence, should be avoided accessing them with objects) which was corrected by C# and hence in C# you can not associate static members with the respective class objects.
In java, some IDEs might issue warnings or errors, if you try to access static members with the respective class objects.