1

Given two classes A and B. B contains an Object A. At the moment of creating a B object we need to have its A object also created. So the question: is it better to instanciate A in the constructor of B or on decalration moment? Let's hava a look at that simple example:

public Class A{
//Staff
}

-- First proposal

public Class B{
//staff
A a;
public B(){
a = new A()
}

}

--Second proposal

public Class B{
//staff
A a = new A();
public B(){
//staff
}
}

So what is the difference between the two solutions?

Houssam Badri
  • 2,441
  • 3
  • 29
  • 60
  • 1
    Instantiating at time of declaration is a common practice to avoid null pointer exceptions. However, in this case, I think it does not really matter, because you are instantiating it anyways. But the former approach lets you skip the constructor definition... – Jay Nov 23 '16 at 10:43
  • 2
    check [this anwser](http://stackoverflow.com/questions/4916735/default-constructor-vs-inline-field-initialization) – grape_mao Nov 23 '16 at 10:43
  • depends on the fact whether you need different `A`s when creating a new `B` or not – XtremeBaumer Nov 23 '16 at 10:43

5 Answers5

2

I think you should either pass an instance of A into constructor for B if you wish to set it via the constructor, or via the appropriate setter. Otherwise you are forcing the two classes to be tightly coupled.

Steve
  • 696
  • 7
  • 15
1

I recommend you to use the first one, because you can add parameters to the constructor.

public Class B {
    A a;
    public B() {
        a = new A();
    }
    public B(A a) {
        this.a = a;
    }
}
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • Initialisers are good when you always need the same initial value (like in your example, an array of given size, or integer of specific value), but it can work in your favour or against you: If you have many constructors that initialise variables differently (i.e. with different values), then initialisers are useless because the changes will be overridden, and wasteful. – Jay Nov 23 '16 at 10:44
1

There is no difference between the two in your specific example.

Generally, if you can go with the second approach (i.e. initializer), use it, because the creation of the object is shared among all constructors.

If you must pass a parameter to A() that comes from B()'s parameter list, the first choice is the only one available, because you cannot pass parameters to field initializers.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Actually there is no difference. Compiler will move initialization code into constructor body. It's just about your code readiness.

Utku Soytaş
  • 1,475
  • 2
  • 19
  • 30
1

Object creation is part of the lifecycle management concern. This is typically a responsability which you want to treat separately. Common patterns are:

  • dependency injection
  • builder, abstract factory or factory method
  • singleton, prototype or object pool

To read up on these see for example Google results for creational patterns and dependency injection.

I will focus here on dependency injection because it is the simplest approach matching your example and results in clean, testable code. Other favorite patterns are builder or factory.

Dependency injection (or Inversion of Control) is a very common pattern (although not usually called a pattern, I think it is one). The best know frameworks offering D.I. are Spring or Java's own CDI but you can also do it by hand as shown below.

Constructor Injection

In your example a simple use of dependency injection could work like this:

public Class Dependency {
}

public Class Application {

    private final Dependency dependency;

    public Application (Dependency dependency) {
          this.dependency = dependency;
    }
}

Usage:

public static void main(String[] args) {
    Application application = new Application(new Dependency());
}

Note that Application is not creating Dependency but expects an instance of Dependency to be supplied to it via the constructor. This is called constructor injection. The advantage of this way is that you can make the dependency field final. A drawback is that, with many dependencies, the constructor might get too many arguments to remain understandable. To avoid that you could use the builder pattern, or use setter injection:

Setter Injection

public Class Dependency {
    public String doStuff(String input) {
        return input + " stuffed";
    }
}

public Class Application {

    private Dependency dependency;

    public void setDependency(Dependency dependency) {
          this.dependency = dependency;
    }

    public String letsGo(String input) {
        String stuff = dependency.doStuff(input);
        return "I called my dependency and it said: " + stuff ;
    }
}

Usage:

public static void main(String[] args) {
    Application application = new Application();
    application.setDependency(new Dependency());
    System.our.println(application.letsGo("rabbit"));
}

Output:

I called my dependency and it said: rabbit stuffed

Testing

Now about testability. Remember, in a unit test I want to be able to test the class Application without testing the class Dependency. If Application was creating its own instance of Dependency this would be hard to do. With dependency injection it's easy. Here's an example using JUnit and Mockito with annotations, which is pretty standard:

@RunWith(MockitoJUnitRunner.class)
public class ApplicationTest {

    @InjectMocks
    private Application instance;
    @Mock
    private Dependency dependency;

    @Test
    public void test() {
        // SETUP
        String testStuff = "some test stuff";
        String input = "Micky";           
        when(dependency.doStuff(input)).thenReturn(testStuff);            

        // CALL
        String actualResult = instance.letsGo(input);

        // VERIFY
        verify(dependency).doStuff(input);
        String expectedResult = "I called my dependency and it said: " + testStuff;
        assertEquals(actualResult, expectedResult); 
    }
}

Here Mockito is creating an instance of Application for you and injects any fields annotated with @Mock into it. It automatically determines to do so via the constructor or a setter. The line:

when(dependency.doStuff(input)).thenReturn(testStuff);

Instructs the mock Dependency to return a specific value when called. This means we are not calling the real Dependency code but asking Mockito to generate a fake result from that class when it is called.

After calling the Application instance you can check if the expected call to the dependency was made as follows:

verify(dependency).doStuff(input);

Mockito checks if the specified call was made exactly once and generates an error if this is not the case.

Then using assertEquals the actual result is compared to the expected result. If the values are not equal, an error is generated by JUnit when you run the test.

So the main lesson from all this is that object creation is an important concern that should ideally be treated separately using one of the creational patterns or dependency injection. By doing this you can focus your class on doing its main task making it easier to understand and test.

Remarks

D.I. itself is probably not considered a pattern because it is not specific enough - you can architect it in several ways. Still, whenever you see code creating instances of its own dependencies you should consider that a code smell and try to refactor it.

The Spring implementation of D.I. uses an abstract factory called the application context. Spring supports injection by simply annotating fields with @Autowired (or @Inject):

@Autowired
private Dependency dependency;

The Dependency instance is obtained by Spring from the application context which is usually an XML file or a class annotated with @Configuration. In the application context you can specify what dependencies (beans) exist and how they should be set up and wired together.

Community
  • 1
  • 1
Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60