In Java, there are many ways to instantiate objects, depending on the scene requirements and design patterns. The following are 7 core object instantiation methods and their principles, applicable scenarios and code examples:
1. new keyword (direct construction)
Principle: Create an object directly by calling the constructor of the class.
Features: The most common and most efficient method, but with high coupling.
Examples:
User user = new User("Alice", 30);
2. Reflection (Reflection)
Principle: Use the newInstance() method of the Class class or the Constructor class to create objects dynamically.
Features: Suitable for dynamic loading classes at runtime (such as in the framework), but have low performance and will bypass compile-time checks.
Examples:
// Method 1: Use () (deprecated, only supports non-parameter-free construction)Class<?> clazz = (""); User user = (User) (); // Method 2: Use () (recommended)Constructor<User> constructor = (, ); User user = ("Bob", 25);
3. Clone
Principle: Copy existing objects by implementing the Cloneable interface and overriding the clone() method.
Features: It is divided into shallow copy (default) and deep copy, and you need to pay attention to the copy of the reference type field.
Examples:
class User implements Cloneable { @Override public User clone() throws CloneNotSupportedException { return (User) (); } } User user1 = new User("Charlie", 28); User user2 = ();
4. Deserialization
Principle: To restore objects from byte streams (such as files, networks), you need to implement the Serializable interface.
Features: Used to persist or cross-network transmission objects, without calling constructors.
Examples:
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(""))) { User user = (User) (); }
5. Factory Method
Principle: Decouple the caller and the specific implementation through factory class encapsulation object creation logic.
Scenario: Used when you need to flexibly switch object types or hide creation details.
Examples:
public interface UserFactory { User createUser(String name, int age); } public class DefaultUserFactory implements UserFactory { @Override public User createUser(String name, int age) { return new User(name, age); } } // useUserFactory factory = new DefaultUserFactory(); User user = ("Dave", 35);
6. Builder mode
Principle: Gradually build complex objects through chain calls to improve code readability.
Scenario: Suitable for scenes where multiple parameters, optional parameters, or require immutable objects.
Examples:
public class User { private final String name; private final int age; private User(Builder builder) { = ; = ; } public static class Builder { private String name; private int age; public Builder name(String name) { = name; return this; } public Builder age(int age) { = age; return this; } public User build() { return new User(this); } } } // useUser user = new ().name("Eve").age(40).build();
7. Dependency Injection
Principle: The object life cycle is managed by a container (such as Spring) and inject dependencies.
Scenario: The core means of enterprise-level application decoupling, supporting scopes such as singletons and prototypes.
Example (Spring annotation method):
@Component public class UserService { private final UserRepository repository; @Autowired // Inject an instance from a Spring container public UserService(UserRepository repository) { = repository; } }
Other edge methods (just understand)
1.Unsafe class: Bypass the constructor by directly allocating memory.
User user = (User) ().allocateInstance();
/MethodHandle: Call the constructor (Java 7+) through the method handle.
3. Dynamic proxy: Generate the proxy object of the interface (such as ()).
Key Summary
Way | advantage | shortcoming | Typical application scenarios |
---|---|---|---|
new keywords | Simple and efficient | High coupling | Create simple objects directly |
reflection | High dynamic | Low performance, bypass compile checking | Framework, plug-in system |
clone | Quickly copy objects | Deep copy needs to be implemented manually | Prototype mode, object reuse |
Deserialization | Recover objects across network/persistent | Security risk, no constructor calls | Cache recovery, RPC transmission |
Factory model | Decoupling Creation Logic | Additional classes are required | Polymorphic object creation |
Builder mode | Strong readability and supports complex object construction | Code redundancy | Multi-parameter, immutable object construction |
Dependency injection | Decoupling and managing object life cycles | Depend on container environment | Enterprise-level applications (such as Spring) |
Best Practices
Preferring to new and factory modes: Keep the code intuitive in simple scenarios.
**Use reflection and Unsafe with caution: Avoid introducing performance and security issues unless necessary (such as framework development).
Depth copying requires caution: Make sure all referenced fields are copied correctly.
Depending on the application: Use containers such as Spring to manage the life cycle of objects in complex systems.
By rationally choosing the instantiation method, the flexibility, maintainability and performance of the code can be improved.
This is the end of this article about 7 ways to instantiate Java objects. For more related contents of instantiated Java objects, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!