A simple definition is:
Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields.
For example a class constructor creates an instance of an object. This class is now dependant on that object. If however this object is passed into the constructor this dependancy is decoupled.
For dependancy injection to work correctly each class requires an interface. This will ensure if the object is switched it will still present the same methods, it doesn’t however need to know what these methods do.
Unit testing as one of the main uses for dependancy injection. It allows objects which perform complex data processing tasks to be replaced with an object which provides mock data for testing. The class being tested doesn’t care how this data is created as long as it’s presented in the same format.
Another example is an object provided SQL database access methods. Using dependancy injection we can switch this to another object with MySQL access methods. As long as both objects expose the same methods the objects using them won’t care which one it is.