SoFunction
Updated on 2025-03-08

Java constructor reuse method

Constructor reuse

Create an Employee class with attributes (name, gender, age, position, salary), and provide 3 constructors that can initialize (⑴) (name, gender, age, position, salary), (2) (name, gender, age) (3) (post, salary). It is required to fully reuse the constructor

 public class Hello {
     public static void main(String[] args) {
         
     }
 }
 class EMployee{
     String name;
     char gender;
     int age;
     String job;
     double sal;
     // Position Salary     public EMployee(String job,double sal) {
          = job;
          = sal;
     }
     // Name Gender Age     public EMployee(String name,char gender,int age) {
          = name;
          = gender;
          = age;
     }
     // Name Gender Age Position Salary     public EMployee(String job,double sal,String name,char gender,int age) {
         this(name,gender,age);
          = job;
          = sal;
     }
 }

It is recommended to use constructor injection

​ The importance of the Spring framework to Java development is self-evident. The IOC that is used the most is the one in it. We use the components to manage the IOC containers in Spring and control the dependencies of objects to Spring to avoid excessive program coupling caused by hard coding.

A few days ago, a friend asked me why I used the constructor injection method. I took time to learn more about it later. The following is what I want to discuss is its injection method.

Three common injection methods

field injection

@Controller
public class FooController {
  @Autowired
  //@Inject
  private FooService fooService;
  
  //Simple use examples, the same below  public List<Foo> listFoo() {
      return ();
  }
}

This injection method should be the most common injection method I have seen in development so far. The reason is very simple:

  • The injection method is very simple: add the field to be injected, attach@Autowired, it can be done.
  • Make the overall code simple and clear, and look beautiful and generous.

Constructor injection

@Controller
public class FooController {
  
  private final FooService fooService;
  
  @Autowired
  public FooController(FooService fooService) {
       = fooService;
  }
  
  //The usage method is the same, omitted}

Setter injection

@Controller
public class FooController {
  
  private FooService fooService;
  
  //The usage method is the same, omitted  @Autowired
  public void setFooService(FooService fooService) {
       = fooService;
  }
}

Benefits of constructor injection

  • Dependency immutable: In fact, it is about final keyword, so I won't explain it more here. Gardeners who don’t understand can go back and check out Java syntax.
  • Dependencies are not empty (excluding our checks on it): When you want to instantiate FooController, since you implement a constructor with parameters, the default constructor will not be called, so you need to pass in the required parameters in the Spring container, so there are two situations: 1. There are parameters of this type -> Pass in, OK. 2: No parameters of this type -> Error is reported. So it is guaranteed not to be empty, Spring will not send a null in.
  • Fully initialized state: This can be combined with the above dependency not empty. Before passing parameters to the constructor, you must ensure that the injected content is not empty, so you must call the dependent component's constructor to complete instantiation. In the process of loading and instantiating Java class, the construction method is the last step (if there is a parent class that initializes the parent class first, then its own member variables, and finally the construction method, which will not be expanded in detail here). So what is returned is the state after initialization.
//Inherit the code injected above field, if the client code uses the following call (or use it in Junit test)//This is just a simulation. Normally, we will only expose the interface to the client, not the implementation.FooController fooController = new FooController();
(); // -> NullPointerException

If field injection is used, the disadvantages are obvious.For environments other than IOC containers, the implementation class cannot be reused except using reflection to provide the dependencies it requires.. And it will always be a potential hidden danger, because you will never be able to detect the existence of NPE without calling it.

Another point worth mentioning is that using field injection may cause cyclic dependencies, that is, B is injected into A and A is injected into B:

public class A {
    @Autowired
    private B b;
}
 
public class B {
    @Autowired
    private A a;
}

If constructor injection is used, when the spring project starts, it will be thrown:

BeanCurrentlyInCreationException:Requested bean is currently in creation: Is there an unresolvable circular reference?

This reminds you to avoid circular dependencies. If it is field injection, there will be no errors when starting, and it will only be reported when using that bean.

Summarize

The above is personal experience. I hope you can give you a reference and I hope you can support me more.