一文總結(jié)使用Java創(chuàng)建對象的八種方式
昨晚加班的時候,同事來旁邊坐著跟我閑聊,不經(jīng)意間看到屏幕上的new 對象代碼,他說:“每次這樣new 一個對象感覺好丑,有沒有更好的方式方法!”。
我說:“有啊,不過也得看場景,簡單的直接用 new 一把梭哈!復(fù)雜的再考慮其它的方式”
那有哪些方式呢?下面來分享一下。
1. new關(guān)鍵字
最直接的創(chuàng)建方式
// 就像我們平時說話:"來一輛新車" Car car = new Car(); // 或者帶參數(shù)的:"來一輛紅色的寶馬" Car bmw = new Car("寶馬", "紅色");
使用場景:這是最常用的方式,適合90%的日常開發(fā)場景。
優(yōu)點:
- 簡單直觀,一眼就能看懂
- 性能好,直接調(diào)用構(gòu)造方法
缺點:
- 不夠靈活,創(chuàng)建邏輯與使用代碼耦合
2. 反射機制
有時候我們需要在運行時才知道要創(chuàng)建什么類的對象,這時候反射就派上用場了。
// 傳統(tǒng)方式:我知道要創(chuàng)建Car
Car car = new Car();
// 反射方式:運行時才知道要創(chuàng)建什么
try {
Class carClass = Class.forName("com.example.Car");
Constructor constructor = carClass.getConstructor();
Car car = (Car) constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
案例:Spring框架中,當(dāng)我們配置了@Component注解的類,Spring就是通過反射來創(chuàng)建這些對象的。
// Spring內(nèi)部大致是這樣做的 Class beanClass = loadClass("com.example.UserService"); Object bean = beanClass.getDeclaredConstructor().newInstance();
3. clone()方法
假設(shè)你有一個配置好的對象,現(xiàn)在需要另一個一模一樣的,這時候clone就很有用。
class UserSettings implements Cloneable {
private String theme = "dark";
private int fontSize = 14;
@Override
public UserSettings clone() {
try {
return (UserSettings) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
// 使用clone
UserSettings original = new UserSettings();
UserSettings cloned = original.clone(); // 得到一個完全相同的副本
注意點:
- 需要實現(xiàn)
Cloneable接口,否則會拋出異常 - 默認是淺拷貝,如果需要深拷貝要自己實現(xiàn)
4. 反序列化
當(dāng)我們把對象保存到文件或通過網(wǎng)絡(luò)傳輸后,需要重新把它變回對象。
// 對象需要實現(xiàn)Serializable接口
class GameSave implements Serializable {
private static final long serialVersionUID = 1L;
private int level;
private int score;
}
// 保存對象到文件
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("save.dat"))) {
oos.writeObject(gameSave);
}
// 從文件讀取對象
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("save.dat"))) {
GameSave loadedSave = (GameSave) ois.readObject();
// loadedSave就是原來那個gameSave的副本
}
5. 靜態(tài)工廠方法
有時候直接new不夠表達我們的意圖,這時候工廠方法就很有用。
class Color {
private int red, green, blue;
private Color(int r, int g, int b) {
this.red = r;
this.green = g;
this.blue = b;
}
// 靜態(tài)工廠方法:語義更明確
public static Color fromRGB(int r, int g, int b) {
return new Color(r, g, b);
}
public static Color fromHex(String hex) {
// 解析十六進制顏色碼
return new Color(/* 解析邏輯 */);
}
public static Color red() {
return new Color(255, 0, 0);
}
}
// 使用:這樣讀起來更自然
Color red = Color.red();
Color custom = Color.fromRGB(255, 128, 0);
優(yōu)點:
- 方法名可以表達創(chuàng)建意圖
- 可以緩存對象,避免重復(fù)創(chuàng)建
- 可以返回子類對象,更靈活
6. Builder模式
當(dāng)對象有很多屬性時,構(gòu)造方法會變得很長很難讀,Builder模式來解決!
class Computer {
private final String cpu; // 必須
private final String ram; // 必須
private final String storage; // 必須
private final String graphicsCard; // 可選
private final String monitor; // 可選
// 私有構(gòu)造方法,只能通過Builder創(chuàng)建
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
this.graphicsCard = builder.graphicsCard;
this.monitor = builder.monitor;
}
public static class Builder {
// 必須參數(shù)
private final String cpu;
private final String ram;
private final String storage;
// 可選參數(shù)
private String graphicsCard = "集成顯卡";
private String monitor = "23寸顯示器";
// Builder構(gòu)造方法包含必須參數(shù)
public Builder(String cpu, String ram, String storage) {
this.cpu = cpu;
this.ram = ram;
this.storage = storage;
}
// 設(shè)置可選參數(shù)的方法
public Builder graphicsCard(String graphicsCard) {
this.graphicsCard = graphicsCard;
return this;
}
public Builder monitor(String monitor) {
this.monitor = monitor;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
// 使用Builder模式:鏈式調(diào)用,非常清晰
Computer gamingPC = new Computer.Builder("i7", "16GB", "1TB SSD")
.graphicsCard("RTX 3080")
.monitor("27寸4K顯示器")
.build();
適用場景:
- 對象有很多屬性,特別是可選屬性很多時
- 希望創(chuàng)建過程更清晰、易讀
- 需要創(chuàng)建不可變對象
7. 匿名內(nèi)部類
當(dāng)我們只需要某個接口的一次性實現(xiàn)時,匿名內(nèi)部類很方便。
// 創(chuàng)建線程的傳統(tǒng)方式
class MyTask implements Runnable {
@Override
public void run() {
System.out.println("執(zhí)行任務(wù)");
}
}
Runnable task1 = new MyTask();
// 使用匿名內(nèi)部類:更簡潔
Runnable task2 = new Runnable() {
@Override
public void run() {
System.out.println("執(zhí)行任務(wù)");
}
};
// Java 8以后,可以用lambda表達式進一步簡化
Runnable task3 = () -> System.out.println("執(zhí)行任務(wù)");
8. 方法引用
Java 8引入了函數(shù)式編程,讓對象創(chuàng)建更加優(yōu)雅。
class Person {
private String name;
public Person() {
this.name = "匿名";
}
public Person(String name) {
this.name = name;
}
}
// 方法引用創(chuàng)建對象
Supplier defaultPerson = Person::new;
Function namedPerson = Person::new;
// 使用
Person p1 = defaultPerson.get(); // 調(diào)用無參構(gòu)造
Person p2 = namedPerson.apply("張三"); // 調(diào)用有參構(gòu)造
總結(jié)
| 場景 | 推薦方式 | 理由 |
|---|---|---|
| 日常開發(fā) | new關(guān)鍵字 | 簡單直接,性能好 |
| 多參數(shù)對象 | Builder模式 | 可讀性好,靈活 |
| 需要封裝創(chuàng)建邏輯 | 靜態(tài)工廠方法 | 隱藏實現(xiàn)細節(jié) |
| 框架開發(fā) | 反射機制 | 動態(tài)性,靈活性 |
| 函數(shù)式編程 | 方法引用 | 代碼簡潔,表達力強 |
| 創(chuàng)建對象副本 | clone()方法 | 語義明確,使用方便 |
簡單場景用new,復(fù)雜對象用Builder,需要靈活性用工廠方法或反射。
到此這篇關(guān)于使用Java創(chuàng)建對象的八種方式的文章就介紹到這了,更多相關(guān)Java創(chuàng)建對象方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaMap兩種遍歷方式keySet與entrySet詳解
這篇文章主要介紹了JavaMap兩種遍歷方式keySet與entrySet,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03
[Spring MVC]-詳解SpringMVC的各種參數(shù)綁定方式
本篇文章主要介紹了SpringMVC的各種參數(shù)綁定方式 ,具有一定的參考價值,有需要的可以了解一下。2016-12-12
SpringBoot快速搭建web項目詳細步驟總結(jié)
這篇文章主要介紹了SpringBoot快速搭建web項目詳細步驟總結(jié) ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12

