3

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?

isnot2bad
  • 24,105
  • 2
  • 29
  • 50
jkim796
  • 55
  • 1
  • 4
  • 2
    possible duplicate of [Why can't I do assignment outside a method?](http://stackoverflow.com/questions/12062481/why-cant-i-do-assignment-outside-a-method) – Robert Moskal Apr 16 '15 at 17:04
  • Are you asking about syntax? Or how class loading and object initialization work in java? Or do you really want to know how to write an assignment statement of an ArrayList with values? – Aaron Kurtzhals Apr 16 '15 at 17:11

6 Answers6

6

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:

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • The class initializer will not be able to access the instance field `list`. – isnot2bad Apr 16 '15 at 17:09
  • @isnot2bad it is not a static initializer, it will run after fields initialization and before constructors. Weird, but it can be used. – Claudio Apr 16 '15 at 17:11
  • @isnot2bad it will because the variable is declared before the class initializer block. – Luiggi Mendoza Apr 16 '15 at 17:13
  • I'm totally puzzled now. I'm using Java almost daily for about 14 years now, but I've never seen/used this! Need a beer now... – isnot2bad Apr 16 '15 at 17:15
  • 1
    @isnot2bad you can always learn something new from everybody ;) and if I can, I would pay that beer. Cheers! – Luiggi Mendoza Apr 16 '15 at 17:17
  • 1
    @isnot2bad kudos you didn't use it. IMHO this is one of the features that tells you you're probably doing something wrong. – Claudio Apr 16 '15 at 17:18
1

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");
    }
}
isnot2bad
  • 24,105
  • 2
  • 29
  • 50
1

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.

Claudio
  • 1,848
  • 12
  • 26
0

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.

Code Whisperer
  • 1,041
  • 8
  • 16
0

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"));
}
Axxiss
  • 4,759
  • 4
  • 26
  • 45
  • If it doesn't have to be an `ArrayList` (or any other mutable List), even `private List foo = Arrays.asList("a", "b", "c");` would do. – blalasaadri Apr 16 '15 at 22:31
0

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"));
mamboking
  • 4,559
  • 23
  • 27
  • You should use `List` interface on the variable definition, and isn't necessary to create a new `ArrayList` as it's already create in `Arrays.asList()` method – Axxiss Apr 16 '15 at 17:12
  • 1
    @Axxiss it is necessary because the `List` returned by `Arrays#asList` doesn't support add/remove operations. – Luiggi Mendoza Apr 16 '15 at 17:14
  • I used ArrayList because the OP did. I have to pass the list to the ArrayList constructor because Arrays.asList() can return any kind of list. – mamboking Apr 16 '15 at 17:14
  • @LuiggiMendoza yes, you right, it's necessary I didn't remember that. – Axxiss Apr 16 '15 at 17:16