views:

148

answers:

5

Hello.

Simple question. A friend of mind wrote code similar to this one (which is just to explain you my question, it's not useful at all....)

class Example{
    private int[] tab = new int[10];
    public Example() {
        for(int i = 0 ; i < 10 ; i++)
            tab[i] = (int)(Math.random()*100);
        for(int i = 0 ; i < 10 ; i++)
            System.out.println(tab[i]);
    }
    public static void main(String[] arg) {
        Example ex = new Example();
    }
}

I told him he should put the new inside the constructor

class Example{
    private int[] tab;
    public Example() {
        tab = new int[10];
    ...
}

When he ask me why, I din't know what to answer : I didn't have a definite argument other than "it's better this way". The way I learn it, you can initialize variables with basic types (int, double...) but for arrays you should do it in the constructor.

So :

  • is it really better ?
  • is there some good reasons : convention ? style ?
  • does it change anything like less/more memory used ?

I'm not considering the case where the number of element can vary. It will ALWAYS be 10

+4  A: 

Actually I prefer using the outer method. If he added a constructor and had

private int[] foo = new int[10];

public Example() { }

public Example(int somethVar) { }

Then both constructors would have a foo array ready for use. See this article as the Java compiler is smart enough to just copy that stuff into the constructor, so it really isn't any better.

Anon
+3  A: 

I'm not aware of any functional/performance advantages of one method or another. But here're some thoughts why initializing variable immediately can be better.

  1. If you have three different constructors, you won't want to put new int[10]; in each, right?
  2. Readability. When I see variable used in the code, I can do 'ctrl-click' in my IDE and see both type and value of it. I don't have to search around for a place where it's initialized.
Nikita Rybak
Comment to 1. It depends, if one constructor does `new int[2]`, and the other `new int[10]` ( hey, that's usually the reason for having multiple constructors ), then you do want them initialized in constructors.
Alexander Pogrebnyak
@Alexander You comment is applicable to both 1 and 2 :) Yes, multiple constructors give you more freedom.
Nikita Rybak
In that case, their was only one constructor. Indeed if the size can vary, you need to initialize it in each constructor.
Loïc Février
+4  A: 
  • is it really better ?

Not really, IMO.

  • is there some good reasons : convention ? style ?

There may be valid reasons for choosing one way over the other is when you have multiple constructors, or when the initial values depend on constructor arguments; e.g.

private int[] tab;

public Example(int size) {
    tab = new int[size];
    for (int i = 0; i < size; i++)
        tab[i] = (int) (Math.random() * 100);
}

or

private int[] tab = new int[10];

public Example(int initial) {
    for (int i = 0; i < 10; i++)
        tab[i] = initial;
}

public Example() {
    for (int i = 0; i < 10; i++)
        tab[i] = (int) (Math.random() * 100);
}

Apart from that (and in your example) there are no general rules about this. It's a matter of personal taste.

  • does it change anything like less/more memory used ?

In your example it will make no difference. In general, there might be a tiny difference in the code size or performance, but it is not worth worrying about.

In short, I don't think your suggestion to your friend has a rational basis.

The way I learn it, you can initialize variables with basic types (int, double...) but for arrays you should do it in the constructor.

You should unlearn that ... or at least recognize that it is just a personal preference.

Stephen C
With more constructors you can still use the this() keyword in another constructor to call an existing one.
Koekiebox
@Koekiebox - yes, if it helps. In my example it wouldn't help.
Stephen C
@Stephen C : understood ! My java knowledge is very bacic and it was something teached to me a while ago during a short project. I accepted it as a fact but the question was raised today, while speeking with my friend.
Loïc Février
I'm guessing the OP comes from the C++ environment. For some reason, in C++ we are told to do our instatiation inside a constructor.
The Elite Gentleman
A: 

I like to initialise my non-static instance variables in the constructor,

doing this makes it easier for other people to recognise which strategy is followed when the constructor is ran.

Each new object will have its very own tab instance, so in your example it doesn't matter if the class stays the same.

The only time I use a constructor is when I need to pass parameters that is applicable to the whole object and not to a specific method, example:

public class Authenticate{
    private String usrname = null;
    private String password = null;
    public Authenticate(String usernameParam,String passwordParam){
        this.usrname = usernameParam;
        this.password = passwordParam;
    }

    public void login(){
        //TODO put some code here to authenticate against some server using some technology.
    }

    public String getDepartment(){
        //Get the department where the username and password variable would be necessary if
        //login hasn't been called.
    }
}
Koekiebox
No need to explicitly initialise those member vars to `null` since 1) they will be initialised to `null` by default anwyay, and 2) you are explicitly assigning values in the constructor.
Grodriguez
Yes, you are initializing them twice.
Steve Kuo
+3  A: 

This is probably going to be a silly question and thus get voted down, but ... why isn't your friend using an initialization block for, you know, initialization?

I understand fully why he doesn't want to put it in the constructor because it might not be the constructor and endlessly repeating the initialization code in each constructor is obviously bad while using a no-arg constructor and relying on the automatic calls to this() can be unnerving.

So...

Here's the code I'd use myself:

class Example{
    private int[] tab;

    { tab = new int[10]; }

    public Example() {
        for(int i = 0 ; i < 10 ; i++)
            tab[i] = (int)(Math.random()*100);
        for(int i = 0 ; i < 10 ; i++)
            System.out.println(tab[i]);
    }
    public static void main(String[] arg) {
        Example ex = new Example();
    }
}

I'd even roughly use that structure: declare my private members, put in the initialization block, declare my constructors, declare the rest of my methods.

JUST MY correct OPINION
IMHO, this is right way)
Stas
I think he didn't used it because he hasn't learned it yet...being in Java101 for like 3 weeks or so.
Loïc Février
That would do it, yes. :)
JUST MY correct OPINION
This not a convention that I've observed in any one else's code ... in my 12+ years of Java experience. In this example, it achieves nothing apart from boosting your LOC count. Nah ... don't like it.
Stephen C
@Stephen C: It boosts your LOC count by... taking up FAR less space than copying the initialization to each constructor in your class? What it "achieves" is putting all of your member initialization in one, easy-to-find place, regardless of whether it's simple initialization (like the above) or complicated initialization (like filling out arrays through for loops). Your class now has everything related put together: member declarations in one place, non-parametrized initialization in a second group, parametrized initialization in the constructors and functionality in the remaining methods.
JUST MY correct OPINION
Avoid separate initializer blocks for single-line initializations. Including the initialization with the declaration is more elegant, more likely to be read correctly, and will not allow the two to become separated.
Andy Thomas-Cramer
In this simple, trivial class that was clearly flagged as being, and I quote, "just to explain you my question, it's not useful at all", you'd be correct. In a more complicated real-world class with both single-line and multi-line initializations you'd be wrong, IMNSHO.
JUST MY correct OPINION
@JMcO - it boosts the LOC count relative to putting the initialization(s) on the declaration(s). This is what most sensible people would do if the initialization was 1) simple, 2) the same for all constructors, and 3) they didn't want to use `this(...)` constructor chaining.
Stephen C
You see, in my world "sensible" is keeping related functionality together. In a trivial class like this, sure, initialize on the declaration. But if you have a class that has some trivial initializations and some not-so-trivial ones (like most classes are likely to be), it is not "sensible" to me to have your non-parametrized initializations in differing locations in your class.
JUST MY correct OPINION