Java 重構和程式碼操作
Visual Studio Code 提供了許多重構原始碼的選項,以及用於在編碼時生成程式碼和修復問題的程式碼操作。要訪問它們,請點選您看到的任何燈泡💡。或者右鍵單擊編輯器檢視並選擇程式碼操作...。
支援的程式碼操作列表
- 重構
- 分配給變數
- 將匿名內部類轉換為巢狀類
- 轉換為匿名類建立
- 轉換為增強 for 迴圈
- 轉換為 lambda 表示式
- 轉換為靜態匯入
- 提取重構
- 內聯重構
- 反轉布林值
- 移動
- 重新命名
- 型別更改
- 程式碼操作
- 支援的其他程式碼操作
重構
Java 程式重構的目的是在不影響程式行為的情況下對系統範圍內的程式碼進行更改。VS Code 的 Java 語言支援提供了許多易於訪問的重構選項。
呼叫重構
重構命令可從編輯器的上下文選單中獲得。選擇要重構的元素,右鍵單擊以開啟上下文選單,然後選擇重構...。

然後您將看到所有可用的重構選項。
分配給變數
將表示式分配給區域性變數或欄位。
示例
之前
Arrays.asList("apple", "lemon", "banana");
之後
List<String> fruits = Arrays.asList("apple", "lemon", "banana");
它還可以用於將引數分配給新欄位,以處理建構函式中未使用的引數。
將匿名內部類轉換為巢狀類
將匿名內部類轉換為成員類。
示例
讓我們將匿名類Interface(){...}轉換為類Clazz的成員。
之前
public class Clazz {
public Interface method() {
final boolean isValid = true;
return new Interface() {
public boolean isValid() {
return isValid;
}
};
}
}
之後
public class Clazz {
private final class MyInterface extends Interface {
private final boolean isValid;
private MyInterface(boolean isValid) {
this.isValid = isValid;
}
public boolean isValid() {
return isValid;
}
}
public Interface method() {
final boolean isValid = true;
return new MyInterface(isValid);
}
}
轉換為匿名類建立
將 lambda 表示式轉換為匿名類建立。
示例
變數runnable已分配了一個 lambda 表示式。讓我們將其轉換為匿名類建立。
之前
public void method() {
Runnable runnable = () -> {
// do something
};
}
之後
public void method() {
Runnable runnable = new Runnable() {
@Override
public void run() {
// do something
}
};
}
另請參閱:轉換為 lambda 表示式
轉換為增強 for 迴圈
將簡單的for迴圈轉換為for-each樣式。
示例
之前
public void order(String[] books) {
for (int i = 0; i < books.length; i++) {
// do something
}
}
之後
public void order(String[] books) {
for (String book : books) {
// do something
}
}
轉換為 lambda 表示式
將匿名類建立轉換為 lambda 表示式。
示例
讓我們將匿名類Runnable(){...}轉換為 lambda 表示式。
之前
public void method() {
Runnable runnable = new Runnable(){
@Override
public void run() {
// do something
}
};
}
之後
public void method() {
Runnable runnable = () -> {
// do something
};
}
另請參閱:轉換為匿名類建立
轉換為靜態匯入
將欄位或方法轉換為靜態匯入。
示例
讓我們將Assert.assertEquals()呼叫轉換為靜態匯入。
之前
import org.junit.Assert;
...
public void test() {
Assert.assertEquals(expected, actual);
}
之後
import static org.junit.Assert.assertEquals;
...
public void test() {
assertEquals(expected, actual);
}
提取到常量
從選定的表示式建立一個靜態 final 欄位並替換為欄位引用,然後重寫同一表示式出現的其他位置。
示例
讓我們將 π 的值3.14提取為一個常量。
之前
public double getArea(double r) {
return 3.14 * r * r;
}
之後
private static final double PI = 3.14;
public double getArea(double r) {
return PI * r * r;
}
另請參閱:內聯常量
提取到欄位
宣告一個新欄位並用選定的表示式初始化它。原始表示式將被欄位的使用替換。
示例
讓我們將變數area提取為Square類的欄位。
之前
class Square {
public void calculateArea() {
int height = 1;
int width = 2;
int area = height * width;
}
}
之後
class Square {
private int area;
public void calculateArea() {
int height = 1;
int width = 2;
area = height * width;
}
}
選擇變數宣告時,將變數轉換為欄位。
提取到方法
建立一個新方法,包含當前選定的語句或表示式,並將選定內容替換為對新方法的引用。此功能有助於清理冗長、混亂或過於複雜的方法。
示例
讓我們將表示式height * width提取到一個新方法中。
之前
public void method() {
int height = 1;
int width = 2;
int area = height * width;
}
之後
public void method() {
int height = 1;
int width = 2;
int area = getArea(height, width);
}
private int getArea(int height, int width) {
return height * width;
}
另請參閱:內聯方法
提取到區域性變數
建立一個新變數,用當前選定的表示式對其進行賦值,並將選定內容替換為對新變數的引用。
示例
讓我們將表示式platform.equalsIgnoreCase("MAC")提取到一個新變數中。
之前
public void method() {
if (platform.equalsIgnoreCase("MAC")) {
// do something
}
}
之後
public void method() {
boolean isMac = platform.equalsIgnoreCase("MAC");
if (isMac) {
// do something
}
}
提取後,您還可以在同一事務中執行重新命名。
另請參閱:內聯區域性變數
內聯常量
用其定義值替換常量引用。
示例
讓我們將常量PI替換為其定義值:3.14。
之前
private static final double PI = 3.14;
public double getArea(double r) {
return PI * r * r;
}
之後
private static final double PI = 3.14;
public double getArea(double r) {
return 3.14 * r * r;
}
另請參閱:提取到常量
內聯區域性變數
用其初始化程式替換冗餘的變數使用。
示例
讓我們將變數isMac直接替換為布林表示式。
之前
public void method() {
boolean isMac = platform.equalsIgnoreCase("MAC");
if (isMac) {
// do something
}
}
之後
public void method() {
if (platform.equalsIgnoreCase("MAC")) {
// do something
}
}
另請參閱:提取到區域性變數
內聯方法
用方法的正文替換對該方法的呼叫。
示例
讓我們將方法getArea(int height, int width)直接替換為表示式height * width。
之前
public void method() {
int height = 1;
int width = 2;
int area = getArea(height, width);
}
private int getArea(int height, int width) {
return height * width;
}
之後
public void method() {
int height = 1;
int width = 2;
int area = height * width;
}
另請參閱:提取到方法
反轉條件
反轉條件中的布林表示式。
示例
讓我們反轉 if 語句中的布林表示式。
之前
public void method(int value) {
if (value > 5 && value < 15) {
// do something
}
}
之後
public void method(int value) {
if (value <= 5 || value >= 15) {
// do something
}
}
反轉區域性變數
反轉區域性布林變數。
示例
讓我們反轉變數valid。
之前
public void method(int value) {
boolean valid = value > 5 && value < 15;
}
之後
public void method(int value) {
boolean notValid = value <= 5 || value >= 15;
}
移動
移動選定的元素並更正所有對這些元素的引用(包括在其他檔案中)。可用的操作包括
- 將類移動到另一個包
- 將靜態或例項方法移動到另一個類
- 將內部類移動到新檔案
示例
讓我們將類Office中的靜態方法print()移動到類Printer。
之前
public class Office {
public static void main(String[] args) {
print();
}
public static void print() {
System.out.println("This is printer");
}
static class Printer { }
}
之後
public class Office {
public static void main(String[] args) {
Printer.print();
}
static class Printer {
public static void print() {
System.out.println("This is printer");
}
}
}
如果靜態方法在其自身類中的使用次數少於在另一個類中的使用次數,則對其執行移動重構。
將類移動到另一個包。目前,檔案資源管理器不支援移動重構。
將內部類移動到新檔案。
重新命名
預設快捷方式:F2
重新命名選定元素並更正所有對這些元素的引用(包括在其他檔案中)。
示例
讓我們將類Foo重新命名為Bar。
之前
public class Foo {
// ...
}
public void myMethod() {
Foo myClass = new Foo();
}
之後
public class Bar {
// ...
}
public void myMethod() {
Bar myClass = new Bar();
}
呼叫“重新命名”重構的快捷方式是 F2。當您在編輯器中對識別符號呼叫快捷方式時,編輯器內會顯示一個小框,您可以在其中更改識別符號的名稱。按 Enter 鍵時,該識別符號的所有引用也會被更改。
檔案資源管理器也支援對資料夾和檔案的重新命名重構。請求更改後,將提供受影響檔案的預覽,您可以決定如何應用這些更改。

將已解析型別更改為 var 型別
使用var宣告區域性變數。
示例
之前
String s = "";
之後
var s = "";
另請參閱:將 var 型別更改為已解析型別
將 var 型別更改為已解析型別
使用已解析型別宣告區域性變數。
示例
之前
var s = "";
之後
String s = "";
另請參閱:將已解析型別更改為 var 型別
程式碼操作
程式碼操作可用於生成常見的程式碼結構和重複元素。其中一些是快速修復,可幫助您即時修復程式碼問題。
生成建構函式
為類新增建構函式。
生成委託方法
生成委託方法
覆蓋/實現方法
使用此程式碼操作,所有候選物件都會以清單形式呈現給您。然後,您可以決定要覆蓋或實現的內容。
整理匯入
您可以使用此程式碼操作來清理您的匯入。它還可以處理歧義匯入,在這種情況下,將顯示一個下拉列表供您選擇正確的選項。還會顯示帶有未解析型別的程式碼行,以幫助您做出決定。
生成 getter 和 setter
您可以批次生成所有新成員變數的 getter 和 setter。如果類有多個欄位,程式碼操作將提示一個快速選擇,供您選擇要用於生成訪問器方法的欄位。
生成hashCode()和equals()
可以使用預設實現生成hashCode()和equals()。列出了所有非靜態成員變數,您可以使用清單來自定義生成的程式碼。
有兩種選項可供您自定義生成的程式碼
- 如果您使用 Java 7 或更高版本,可以將
java.codeGeneration.hashCodeEquals.useJava7Objects設定為true,以生成更短的程式碼,該程式碼呼叫Objects.hash和Objects.equals。 - 您還可以將
java.codeGeneration.hashCodeEquals.useInstanceof設定為true,以使用instanceOf運算子來檢查物件型別,而不是呼叫Object.getClass()。
生成toString()
有一個新的程式碼操作可以生成 toString() 方法。可以透過包含所有成員變數的清單進行自定義。
將修飾符更改為 final(如果可能)
將 final 修飾符新增到當前原始檔中的所有變數和引數。
示例
之前
public class Clazz {
public void method(int value) {
boolean notValid = value > 5;
if (notValid) {
// do something
}
}
}
之後
public class Clazz {
public void method(final int value) {
final boolean notValid = value > 5;
if (notValid) {
// do something
}
}
}
修復不可訪問的引用
此快速修復可幫助您修復不可訪問的引用。
建立不存在的包
當您的包名與資料夾名不匹配時,您可以選擇在原始碼中更改包名,或者在檔案系統中移動資料夾(即使目標資料夾尚不存在)。
支援的其他程式碼操作
VS Code 支援的程式碼操作列表不斷增長,上面僅列出了最受歡迎的一些。其他值得注意的支援的操作包括(但不限於):
- 建立未解析的型別
- 移除
final修飾符 - 移除不必要的型別轉換
- 移除冗餘介面
- 在 switch 語句中新增缺失的 case 標籤
- 跳轉到 break/continue 的定義
- 更正對靜態元素的訪問