0. 前言

还在为没有对象而彷徨吗?😧还在为没有对象而迷茫吗?😫还在为没有对象而自我怀疑吗?😭还在担心没有对象怎么办?

简单啊,自己 new 一个啊!!众所周知,程序员是不需要不缺对象的,特别是 JAVA 程序员😲。那除了直接使用 new 关键字创建对象,还有什么其他方法创建对象吗?当然有了。接下来就简单介绍几种创建对象的方法。还是单身的程序员们别怕啦!!😜马上就可以精心挑选一个自己满意的对象方法了🎉🎉🎉

假设我们已经有一个女朋友类:

1
2
3
4
5
6
7
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GirlFriendFriend {
private String name;
private Integer age;
}

注解使用的是 Lombok 框架注解,方便快速开发。

1. new 关键字

这是最常见的创建对象的方式,通过 new 关键字,Java 会在堆内存中为对象分配空间,并返回指向这个对象的引用。

1
2
3
4
5
6
public class Main {
public static void main(String[] args) {
GirlFriend girl = new GirlFriend("小诗诗", 18);
System.out.println(girl);
}
}
1
GirlFriend(name=小诗诗, age=18)

2. 类派发(反射)

Class 的 getDeclaredConstructor().newInstance() 方法可以在运行时创建一个类的新实例。它等效于使用 new 操作符,但是语法更加动态。

1
2
3
4
5
6
7
8
public class Main {
public static void main(String[] args) throws Exception {
GirlFriend girlFriend = GirlFriend.class.getDeclaredConstructor().newInstance();
girlFriend.setName("小诗诗");
girlFriend.setAge(18);
System.out.println(girlFriend);
}
}
1
GirlFriend{name='小诗诗', age=18}

3. 构造器(反射)

Constructor 的 newInstance() 方法可以在运行时创建一个类的新实例,并且可以传入构造函数的参数。这种方式比 Class 的 newInstance() 方法更加灵活,因为可以选择不同的构造函数。

1
2
3
4
5
6
7
public class Main {
public static void main(String[] args) throws Exception {
Constructor<GirlFriend> constructor = GirlFriend.class.getConstructor(String.class, Integer.class);
GirlFriend girlFriend = constructor.newInstance("小诗诗", 18);
System.out.println(girlFriend);
}
}
1
GirlFriend(name=小诗诗, age=18)

4. 动态加载(反射)

知道类全路径,使用 Class.forName() 获取类的 Class 对象,然后调用其 newInstance() 方法创建对象。

1
2
3
4
5
6
7
8
9
public class Main {
public static void main(String[] args) throws Exception {
GirlFriend girlFriend = (GirlFriend) Class.forName("com.muyoukule.GirlFriend")
.getDeclaredConstructor().newInstance();
girlFriend.setName("小诗诗");
girlFriend.setAge(18);
System.out.println(girlFriend);
}
}
1
GirlFriend(name=小诗诗, age=18)

5. clone()方法

如果一个类实现了 Cloneable 接口并重写了 Object 类中的 clone() 方法,那么可以通过调用已有对象的 clone() 方法来创建该对象的一个副本。

PS:clone() 方法默认是受保护的,并且可能抛出 CloneNotSupportedException 异常。😅

因此如果要在类外部使用它,通常需要将其声明为公共的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GirlFriend implements Cloneable {
private String name;
private Integer age;

// 访问权限为 public,并且返回值写为 girl
@Override
public GirlFriend clone() {
try {
return (GirlFriend) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
1
2
3
4
5
6
7
8
9
10
public class Main {
public static void main(String[] args) {
GirlFriend girlFriend1 = new GirlFriend("小诗诗", 18);
GirlFriend girlFriend2 = girlFriend1.clone();

System.out.println("girlFriend1===>" + girlFriend1);
System.out.println("girlFriend2===>" + girlFriend2);
System.out.println(girlFriend1 == girlFriend2); //false
}
}
1
2
3
girlFriend1===>GirlFriend(name=小诗诗, age=18)
girlFriend2===>GirlFriend(name=小诗诗, age=18)
false

6. 反序列化

序列化/反序列化?序列化/反序列化,我忍你很久了,淦!

如果你有一个对象的序列化表示(例如一个文件或一个字节流),你可以使用反序列化来重新创建该对象。这通常通过 ObjectInputStream类完成。

1
2
3
4
5
6
7
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GirlFriend implements Serializable {
private String name;
private Integer age;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Main {
public static void main(String[] args) throws Exception {
GirlFriend girlFriend1 = new GirlFriend("小诗诗", 18);
Path path = Paths.get("girlFriend.txt");
ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(path));
oos.writeObject(girlFriend1);
oos.close();
ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(path));
GirlFriend girlFriend2 = (GirlFriend) ois.readObject();
ois.close();

System.out.println("girlFriend1===>" + girlFriend1);
System.out.println("girlFriend2===>" + girlFriend2);
System.out.println(girlFriend1 == girlFriend2); //false
}
}
1
2
3
girlFriend1===>GirlFriend(name=小诗诗, age=18)
girlFriend2===>GirlFriend(name=小诗诗, age=18)
false

7. 工厂模式

工厂方法是一种设计模式,用于创建对象而不直接使用 new 关键字。工厂方法通常封装了对象的创建逻辑,并且可以根据不同的参数返回不同类型的对象。

1、定义一个 Girl 接口

1
2
public interface Girl {
}

2、让 GirlFriend 继承 Girl接口

1
2
3
4
5
6
7
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GirlFriend implements Girl {
private String name;
private Integer age;
}

3、创建一个 GirlFactory 工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class GirlFactory {
public Girl createGirl(String type) {
if (type == null || type.trim().length() == 0) {
return null;
}
Girl girl = null;
if ("GirlFriend".equals(type)) {
girl = new GirlFriend("小诗诗", 18);
} else {
throw new IllegalArgumentException("Unsupported type: " + type);
}
return girl;
}
}
1
2
3
4
5
6
7
public class Main {
public static void main(String[] args) {
GirlFactory factory = new GirlFactory();
GirlFriend girlFriend = (GirlFriend) factory.createGirl("GirlFriend");
System.out.println(girlFriend);
}
}
1
GirlFriend(name=小诗诗, age=18)

8. Builder模式

Builder 模式用于创建复杂的对象,允许用户以不同的方式构建对象。它通常涉及到一个 Builder 类,该类包含了一系列设置对象属性的方法,并最终返回一个构建好的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GirlFriend {
private String name;
private Integer age;

public GirlFriend(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}

public static class Builder {
private String name;
private int age;

public Builder withName(String name) {
this.name = name;
return this;
}

public Builder withAge(int age) {
this.age = age;
return this;
}

public GirlFriend build() {
return new GirlFriend(this);
}
}
}
1
2
3
4
5
6
7
8
9
public class Main {
public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend.Builder()
.withName("小诗诗")
.withAge(18)
.build();
System.out.println(girlFriend);
}
}
1
GirlFriend(name=小诗诗, age=18)

总结

没有对象不要彷徨、不要迷茫、不要自我怀疑。在上面的方法中精心挑选一个自己满意的方法去造对象吧!!😊

记住,没有对象就自己zao,以后别再说自己没对象了,Java 程序员从不说自己没对象!!!