Dependency injection is a technique where dependencies are provided to classes through constructors, setters, or interfaces rather than having the class create the dependencies directly. This allows for looser coupling between classes and makes testing easier. Common forms of dependency injection include constructor injection, setter injection, and interface injection. While dependency injection improves testability, it can also leak implementation details and prevent deferred creation of dependencies, so it should be used carefully.