Java 重构与源动作
Visual Studio Code 提供了多种重构源代码和源代码作(Source Actions)选项,用于生成代码并在编码过程中解决问题。要访问这些内容,请点击灯泡💡 只要你看到它。或者右键点击编辑器视图,选择“源作......”。
支持的代码动作列表
- 重构
- 赋值到 变量
- 将匿名类转换为嵌套类
- 转换为匿名类创建
- 转换为增强型 for 循环
- 转换为λ表达式
- 转换为静态导入
- 摘录重构
- 内联重构
- 反元布尔
- 让开
- 更名
- 类型变更
- 源头动作
- 支持的其他代码动作
重构
Java 程序重构的目标是在不影响程序行为的情况下,进行系统范围的代码更改。VS Code 的 Java 语言支持 提供了许多易于访问的重构选项。
调用重构
重构命令可通过编辑器的上下文菜单调用。选择你想重构的元素,右键点击打开右键菜单,然后选择重构......:

然后你会看到所有可用的重构选项。
赋值到 变量
将表达式赋值到局部变量或字段。
示例
之前
Arrays.asList("apple", "lemon", "banana");
之后
List<String> fruits = Arrays.asList("apple", "lemon", "banana");
它还可用于为构造器中未使用的参数分配到新字段。
将匿名类转换为嵌套类
将一个匿名的内类转换为成员类。
示例
我们转换匿名类Interface(){...}与该阶级成员咔嚓.
之前
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 表达式转换为匿名类创建。
示例
变量可运行被赋予一个λ表达式。我们把它转换成一个匿名的类创建。
之前
public void method() {
Runnable runnable = () -> {
// do something
};
}
之后
public void method() {
Runnable runnable = new Runnable() {
@Override
public void run() {
// do something
}
};
}
另见:转换为λ表达式
转换为增强型 for 循环
简单映射对于环路到对每个风格。
示例
之前
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
}
}
转换为λ表达式
将匿名类创建转换为λ表达式。
示例
我们转换匿名类Runnable(){...}到λ表达式。
之前
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);
}
提取至常数
从所选表达式创建一个静态的最终字段,并替换一个字段引用,然后重写出现相同表达式的其他位置。
示例
让我们提取π的值: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;
}
另见:内联常数
从抽取到场
声明一个新字段,并用所选表达式初始化。原表达式被场的使用所取代。
示例
我们提取变量区域到该类域方形.
之前
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;
}
}
选择变量声明时,将变量转换为字段。
从提取到方法
创建一个包含当前选择语句或表达式的新方法,并用新方法的引用替换选中内容。此功能对于清理冗长、杂乱或过于复杂的方法非常有用。
示例
我们提取表达式高度 * 宽度换成一种新的方法。
之前
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
}
}
提取完成后,你也可以在同一交易中进行重命名。
另见:内联局部变量
直列常数
用定义值替换常数引用。
示例
我们替换常数私家侦探到其定义值: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)直接映射到表达式高度 * 宽度.
之前
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
}
}
反转局部变量
反转局部布尔变量。
示例
我们反演变量有效.
之前
public void method(int value) {
boolean valid = value > 5 && value < 15;
}
之后
public void method(int value) {
boolean notValid = value <= 5 || value >= 15;
}
让开
移动所选元素并纠正所有对该元素的引用(其他文件中的引用)。可用的行动包括:
- 把班级转到另一个套餐
- 将静态方法或实例方法迁移到另一个类
- 将内类迁移到新文件
示例
让我们来移动静态方法print()来自课堂办公室上课打印机.
之前
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
重命名所选元素并纠正所有对该元素的引用(其他文件中的引用)。
示例
我们给这个类别重新命名吧福到酒吧
之前
public class Foo {
// ...
}
public void myMethod() {
Foo myClass = new Foo();
}
之后
public class Bar {
// ...
}
public void myMethod() {
Bar myClass = new Bar();
}
调用重命名重构的快捷方式是 F2。当你在编辑器中调用某个标识符时,编辑器内会显示一个小框,你可以更改标识符名称。当你按下回车键时,所有对该标识符的引用也会被更改。
文件资源管理器也支持重命名重构,适用于文件夹和文件。请求更改后,会预览受影响文件,您可以决定如何应用这些更改。

将已解析类型改为var类型
用途VAR以声明局部变量。
示例
之前
String s = "";
之后
var s = "";
另见:将变量类型更改为解析类型
将var类型改为解析类型
使用解析类型声明本地变量。
示例
之前
var s = "";
之后
String s = "";
源头动作
源动作可以用来生成常见的代码结构和重复出现的元素。其中一些是快速修复,帮助你实时修复代码问题。
生成构造子
为该类添加一个构造函数。
生成代理方法
生成代理方法
覆盖/实现方法
通过这个源行动,所有候选人都会被呈现给你一份清单。然后你可以决定覆盖或实现哪些。
组织导入
你可以用这个源作来清理导入。它也可以处理歧义导入,在这种情况下,会显示一个下拉列表,供你选择合适的导入。未解决类型的代码行也会显示给你,帮助你做出决定。
生成抓取者和二传者
你可以批量生成所有新成员变量的获取器和设置器。如果类有多个字段,源作会提示快速选择,让你选择用于生成访问器方法的目标字段。
生成hashCode()以及等值()
hashCode()以及等值()可以用默认实现生成。所有非静态成员变量都列出了,你可以用检查列表自定义生成代码。
你可以选择两种方式自定义生成代码:
- 如果你用的是Java 7+,你可以设置
java.codeGeneration.hashCodeEquals.useJava7Objects到确实如此生成更短的调用代码Objects.hash以及Objects.equals. - 你也可以设置
java.codeGeneration.hashCodeEquals.useInstanceof到确实如此使用实例作符来检查对象类型,而不是调用Object.getClass().
生成toString()
有一个新的源动作来生成toString()方法。通过所有成员变量的检查列表,可以进行自定义。
尽可能将修饰符改为结尾
补充决赛修改器对当前源文件中的所有变量和参数。
示例
之前
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 支持的代码动作列表持续增长,仅列出上述最受欢迎的动作。其他值得注意的支持动作包括(但不限于):
- 创建未解决类型
- 移除
决赛修饰语 - 去除不必要的石膏
- 移除冗余接口
- 在切换语句中添加缺失的格标签
- 跳转到休息/继续时的定义
- 正确访问静态元素