文章目录
- 支持的代码操作列表
- 调用重构
- 分配变量
- 字段和局部变量的差别
- Assign statement to new local variable
- 在有参构造函数中将参数指定成一个新的字段
- 将匿名类转换为嵌套类
- 什么是匿名类?
- 匿名类转换为嵌套类的完整演示
- 转换为Lambda表达式
- Lambda 表达式是什么?
- 转换为Lambda
- 转换为匿名类创建
- 转换为增强的 for 循环
- 转换为静态导入
- 提取常量
- 内联常量
- 提取到字段
- 提取方法
- 内联方法
- 提取本地变量
- 内联局部变量
- 反转条件
- 转换本地变量
- 移动
- 重命名
- 源代码操作
- 产生构造器
- 产生代理方法
- 重新/实现方法
- 参考
VS Code提供了许多重构源代码的选项,以及在编码时生产代码和修改问题的源操作,使用的方式有两种:
- 💡- 点击蓝灯泡
- 右键单击编辑器视图,选择 Source Action
支持的代码操作列表
- 重构
- 分配变量
- 将匿名类转为嵌套类
- 转换为匿名类创建
- 转换为增强的 for 循环
- 转换为lambda表达式
- 转换为静态导入
- 提取重构
- 提取为常量
- 提取到字段
- 提取到方法
- 提取到局部变量
- 内联重构
- 内联常量
- 内联局部变量
- 内联方法
- 反转布尔值
- 反转条件
- 反转局部变量
- 移动
- 重命名
- 类型更改
- 将解析类型更改为 var类型
- 将var类型更改为已解析类型
- 源代码操作
- 生成构造函数
- 生成委托方法
- Override/implement 方法
- 组织导入
- 生成getter和setter
- 生成hashCode()和equals()
- 生成toString()
- 将modifiers 更改为 final
- 支持其他的代码操作
- 修复不可访问的引用
- 创建不存在的包
调用重构
重构命令在编辑器的上下文菜单中获取,选中需要重构的元素,右键单击打开上下文菜单,选择 Refactor...
分配变量
字段和局部变量的差别
- Assign statement to new field
- Assign statement to new local variable
new field 是一个新的类的属性, new local variable 是一个新的本地变量。两者的差别的示例如下:
字段
asList 作为类的一个字段
public class Refactor {
List<String> asList;
public void assignToVar() {
asList = Arrays.asList("Liu","Guan","Zhang");
}
}
本地局部变量:
asList 作为方法体内的一个本地局部变量
public class Refactor {
public void assignToVar() {
List<String> asList = Arrays.asList("Liu","Guan","Zhang");
}
}
Assign statement to new local variable
将一个表达式指定给局部变量或字段。
步骤:
- 选中代码
- 右键单击弹出菜单,点击
Refactor...
- 点击 “Assign statement to new local variable”
重构前代码:
Arrays.asList("Liu","Guan","Zhang");
重构后的代码:
List<String> asList = Arrays.asList("Liu","Guan","Zhang");
在有参构造函数中将参数指定成一个新的字段
点击 “Assign all parameters to new fields” 之后产生的代码如下:
public class Refactor {
private String id;
private String name;
publicRefactor(String id,String name){
this.id = id;
this.name = name;
}
注意:
- 选中 name 或是 id之后, 点击前面的小黄灯会出现弹出菜单。
将匿名类转换为嵌套类
什么是匿名类?
什么是Java中的匿名类? 直接看示例代码:
public class AnonymousClass {
interface Hello {
void sayHello();
}
public static void main(String[] args) {
// 使用匿名类创建Hello 接口的实例
Hello hello = new Hello() {
@Override
public void sayHello() {
System.out.println("Hello!");
}
};
// 调用sayHello方法
hello.sayHello();
}
}
这里在类 AnonymousClass 定义了一个接口 Hello,该接口有一个接口方法 sayHello(),在创建Hello 接口实例的时候实现了sayHello()的方法。
匿名类是指在使用时直接定义的类,而不需要先定义类然后再使用。在Java中,匿名类的主要作用有:
- 简化代码
- 用于创建回调函数 (调用的时候再实现)
匿名类转换为嵌套类的完整演示
完整步骤:
- 首先有一个自定义的接口 MyInterface
public interface MyInterface {
}
- 接下来有一个获取接口示例的方法 getMyInterface(),在该方法中定义了类的方法hello()
public MyInterface getMyInterface() {
return new MyInterface() {
public void hello() {
System.out.println("Hello");
}
};
}
完整的代码如下:
/**
* Description:
* Author: XM
* Date: 2024-02-13
*/
package com.osxm.je.chp5.vscode;
public class AnonymousToNestedClass {
public interface MyInterface {
}
public MyInterface getMyInterface() {
return new MyInterface() {
public void hello() {
System.out.println("Hello");
}
};
}
}
以上步骤之后在hello() 方法前面会出现蓝色小灯泡,也可以选择 hello() 之后右键单击,在弹出菜单中选择"Refactor…",再点击 “Convert anonymous to nested class”。点击完成产生的代码如下:
public class AnonymousToNestedClass {
private final class MyInterfaceImplementation implements MyInterface {
public void hello() {
System.out.println("Hello");
}
}
public interface MyInterface {
}
public MyInterface getMyInterface() {
return new MyInterfaceImplementation();
}
}
转换为Lambda表达式
将匿名类创建转换为Lambda表达式。
Lambda 表达式是什么?
Lambda表达式是一种匿名函数,它可以在代码中以内联的方式定义和使用。Lambda表达式可以简洁地表示一个函数,通常用于需要函数作为参数或返回值的情况。Lambda表达式的语法比较简洁,由箭头符号 “->” 分隔左右两部分,左侧为参数列表,右侧为函数体。
Lambda表达式的一般形式为: (参数列表) -> 函数体
Lambda表达式可以有0个或多个参数,多个参数之间用逗号分隔。函数体可以是一个表达式,也可以是一个代码块。
Lambda表达式的特点包括:
- 匿名性:Lambda表达式没有名字,所以可以用作匿名函数。
- 简洁性:Lambda表达式可以简洁地表示一个函数,避免了定义命名函数的麻烦。
- 内联性:Lambda表达式可以在代码中直接定义和使用,不需要额外的函数定义和调用。
Lambda表达式常用于函数式编程中的高阶函数和匿名函数的编写,可以大大简化代码的编写和阅读。
在Java中,简言之, 接口只有一个需要被实现的方法,可以使用Lambda表达式,以线程接口 Runnable 为例,该接口只有一个run() 方法。线程类可以通过实现该接口,实现该类中的run()方法,看一个完整的示例:
/**
* Description:
* Author: XM
* Date: 2024-02-14
*/
package com.osxm.je.chp5.vscode;
public class AnonyClassCreateToLambda {
public Runnable myRunnable(){
Runnable runnable = new Runnable(){
@Override
public void run(){
System.out.println("Hello");
}
};
return runnable;
}
public static void main(String[] args) {
AnonyClassCreateToLambda anonyToLambda = new AnonyClassCreateToLambda();
Thread thread = new Thread(anonyToLambda.myRunnable());
thread.start();
}
}
转换为Lambda
选中 Runable 之后右键单击,在弹出的菜单中选中 “Convert to lambda expression”
转换后的lambda表达式如下:
public Runnable myRunnable(){
Runnable runnable = () -> System.out.println("Hello");
return runnable;
}
转换为匿名类创建
和上面的步骤相反, 使用VS Code 也可以将Lambda表达式转换为匿名类创建。
对于以下的Lambda表达式:
public Runnable myRunnable(){
Runnable runnable = () -> System.out.println("Hello");
return runnable;
}
选中Lambda表达式,右键单击,在弹出菜单中选择“Convert to lambda expression”。
转换后的匿名类创建的代码如下:
public Runnable myRunnable(){
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
return runnable;
}
转换为增强的 for 循环
将简单的for 循环转换为 for-each 风格。
以如下的循环代码为例:
List<String> list = Arrays.asList("1");
for(int i =0;i<list.size();i++){
System.out.println(list.get(i));
}
在VS Code 中选中 for 的关键字之后右键单击,在弹出的菜单中选择"Convert to enhanced ‘for’ loop"。
转换后的代码如下:
for (String element : list) {
System.out.println(element);
}
注意: 一定要选择 for 关键字才会在弹出菜单中出现"Convert to enhanced ‘for’ loop" 。
转换为静态导入
将字段或方法转换为静态导入。
这里以 Arrays 的asList() 方法为例, 初始化一个字符串的列表可以使用如下代码:
List<String> list = Arrays.asList("hello");
选中asList关键字之后右键单击 或者是点击前面的黄色小灯,在弹出的菜单中选择"Convert to static import"
转换后的代码如下:
提取常量
从选择的表达式创建一个静态的 final 字段并且替换。
以如下代码为例:
public double getAreaAfter(double r) {
return 3.14 * r * r;
}
选取 3.14 之后单击右键,在弹出菜单中选中 “Extract to constant”
转换后的代码如下:
private static final double _3_14 = 3.14;
public double getAreaAfter(double r) {
return _3_14 * r * r;
}
内联常量
将常量引用替换为其定义的值。
转换前:
private static final double PI = 3.14;
public double inlineConstantBefore(double r){
return PI * r * r;
}
选中上面的 PI之后,点击小黄灯之后选择 “Inline Constant”
转换后:
public double inlineConstantAfter(double r){
return 3.14 * r * r;
}
提取到字段
定义一个新的字段并使用选择表达式初始化。
示例:
转换前:
public void extractFieldBefore(){
int height =1 ;
int width = 2;
int area = height * width;
}
选中上面的 area 之后,右键单击或点击小黄灯之后选择"Extract to field"。
转换后:
private int area;
public void extractFieldAfter(){
int height =1 ;
int width = 2;
area = height * width;
}
提取方法
创建一个包含当前所选语句或表达式的新方法,并将所选内容替换为对新方法的引用。此功能对于清理冗长、杂乱或过于复杂的方法非常有用。
示例:
转换前:
public void extractMethodBefore(){
int height =1 ;
int width = 2;
int area = height * width;
}
选中表达式之后,点击 “Extra to method”
public void extractMethodAfter(){
int height =1 ;
int width = 2;
getArea(height, width);
}
private void getArea(int height, int width) {
int area = height * width;
}
内联方法
将方法的调用替换为方法体。
示例:
转换前:
public void inlineMethodBefore(){
int height =1 ;
int width = 2;
int area = getArea(height,width);
}
private int getArea(int height,int width){
return height * width;
}
转换后:
public void inlineMethodAfter() {
int height = 1;
int width = 2;
int area = height * width;
}
提取本地变量
创建指定给当前选定表达式的新变量,并使用对新变量的引用替换选定内容。
示例:
转换前:
public void extraLocalVarBefore(String fruit){
if("Apple".equals(fruit)){
//
}
}
选中 "Apple".equals(fruit)
,点击小黄灯或右键单击,之后选择 “Extra to local variable”。
转换后的代码如下:
public void extraLocalVarAfter(String fruit){
boolean equals = "Apple".equals(fruit);
if(equals){
//
}
}
内联局部变量
用其初始值设定项替换冗余变量用法。
转换前:
public void inlineLocalVarBefore(String fruit){
boolean equals = "Apple".equals(fruit);
if(equals){
//
}
}
选中上面的equals 之后,点击小黄灯,选择 Inline local variable,
转换后:
public void inlineLocalVarAfter(String fruit){
if("Apple".equals(fruit)){
//
}
}
反转条件
反转条件中的布尔表达式。
示例:
转换前:
public void invertCondBefore(int value){
if(value >1 && value <3){
}
}
选中条件表达式的内容,选中 “Invert conditions”:
转换后的内容:
public void invertCondAfter(int value){
if(value <= 1 || value >= 3){
}
}
转换本地变量
转换本地布尔变量。
示例:
转换前:
public void invertLocalVarBefore(int value){
boolean valid = value >1 && value <3;
}
点击 valid 之后 ,点击小黄灯之后,选择"Invert local variable"。
转换后:
public void invertLocalVarAfter(int value){
boolean notValid = value <= 1 || value >= 3;
}
移动
将选中的元素移动到指定位置(或是其他文件),可选择的动作:
- 将类移动到其他包
- 将静态或实例方法移动到其他类
- 移动内部类到一个新文件
示例:
转换前:
public class MoveBefore {
public static void main(String[] args) {
print();
}
public static void print() {
System.out.println("This is printer");
}
static class Printer {
}
}
选中需要移动的方法名,之后点击前面的小黄灯之后选择 “Move ‘print()’”
重命名
重命名选择的元素并更正所有引用。
类文件的命令可以有多种方式:
-
右键单击文件名,在弹出菜单选择 “Rename”
-
在编辑器中选中类名, 按Fn + F2 键会弹出重命名的小窗口。
源代码操作
源操作可用于生成通用代码结构和重复出现的元素。其中一些是快速修复程序,可以快速修复代码问题。
产生构造器
在编辑器中右键单击选中 “Source Action…”,选中 “Generate Constructors…”
接下来会选择构造器需要的参数
public class SourceAction {
private String name;
public SourceAction(String name) {
this.name = name;
}
}
产生代理方法
示例:
有一个代理类Delegate ,该类有一个代理方法 delegateMethod()。
public class Delegate {
public void delegateMethod(){
}
}
有一个接收类DelegateRecevier,该类中有一个Delegate类型的成员变量。
右键单击编辑器,选择 “Source Action…” 之后选择 “Generate Delegate Methods…”,之后可以选择需要产生的代理方法:
产生后的代码:
public class DelegateRecevier {
private Delegate delegate;
public void delegateMethod() {
delegate.delegateMethod();
}
}
重新/实现方法
选择 “Override/Implement Methods…”
参考
- https://code.visualstudio.com/docs/java/java-refactoring