学会 Eclipse 重构,让开发飞起来~

何为重构

重构,在《重构,改善既有代码的设计》这本经典的书中给出了定义,大概就是:在不改变代码对外的表现的情况下,修改代码的内部特征。说白了,就是我们的测试用例不变,然后我们对既有的代码的结构进行修改。重构在软件开发中是经常遇到的,也是非常重要的。

当项目做到一定程度后,代码重构是必然的。重构可以改善既有代码的可读性,可扩展性,可维护性。

Eclipse 的重构

重构一般都涉及到比较大量的改动。手工重构很容易引起代码错误,如果是编译问题还比较容易发现,如果是导致运行期问题那就很糟糕。本来是想把代码重构的更好,最后却引起生产问题,那是得不偿失的。

Eclipse 作为 Java 开发利器,提供了很多方便重构的功能。能够为 Java 类、成员、方法、代码块进行多种类型的自动重构。

常用重构方法

重构 Eclipse 功能都在“Refactor”菜单下,下面就讲解中常用的几种重构方法。

Rename(重命名)

修改 Java 元素的名字,包括:类名、变量名、方法名。当然你也可以自己手动修改,但是当一个元素被多个地方引用到时,那就需要改动很多地方。Eclipse 则可以将引用到的地方统统一起改了。快捷键:Alt+Shift+R

如图,写完名字后回车即可:

重命名示例

Move(移动)

用来将类从一个包移动到另一个包。当然引用的地方也会跟着改。

如图,选完要移入的包,确认即可:

移动

Change Method Signature(修改方法签名)

这个功能在重构时很有用,修改方法签名包括方法的作用域,返回类型,名称,入参的类型、名称、数量、顺序。而且如果是在接口或父类上改了,它的实现类和子类也会跟着改。需要注意的是,如果增加了一个参数,那么这个方法原来调用的地方默认会传 null,这很可能不是我们想要的。

如图:

修改方法签名

Extract Method(提取方法)

当我们的一个方法里面的代码很长时,我们总是会需要将里面的代码块抽取出来,单独作为一个方法维护。“提取方法”功能可以快速方便的实现。

选中需要提取的代码块,如图,提取前:

提取方法前

提取后:

提取方法后

Extract Local Variable(提取局部变量)

使用一个变量来代替一个表达式有很多好处。如果表达式在多处被使用,这样能够提高性能,而且也提高了代码的可读性。选择需要提取为局部变量的表达式,在弹出框中输入变量名即可:

比如,提取前:

1
2
3
public String method1(String arg0, String arg1) {
return "hello" + "world";
}

选中:"hello " + "world",提取后:

1
2
3
4
public String method1(String arg0, String arg1) {
String helloWorld = "hello" + "world";
return helloWorld;
}

Extract Constant(提取常量)

提炼常量与提取局部变量很相似,不过提取出来的是类的 static final 成员变量。

比如,提取前:

1
2
3
public String method1(String arg0, String arg1) {
return "hello" + "world";
}

选中:"hello " + "world",提取后:

1
2
3
4
5
private static final String HELLO_WORLD = "hello" + "world";

public String method1(String arg0, String arg1) {
return HELLO_WORLD;
}

Convert Local Variable to Field(转换局部变量为常量)

转换局部变量为成员变量,将方法内的变量声明移动到方法所在类中,使该变量对整个类可见。选择一个局部变量,从重构菜单中选择转换局部变量为成员变量项,随后打开配置的对话框。在此对话框中,添入成员变量的名字,选择修饰词等。

如图,转换前:

转换前

转换后:

转换后

Move Type to New File(移动类到新的文件)

当一个文件中有多个类,或类下面有内部类时。我们可以将此类提取出来,创建一个新文件类维护该类。

比如,A 类和 B 类都在 A.java 文件中,我们可以将 B 类提取出来。提取前:

1
2
3
4
5
6
7
8
9
10
11
12
public class A {

private String helloWorld = "hello" + "world";

public String method1(String arg0, String arg1) {
return helloWorld;
}
}

class B {
private String name = "张三";
}

提取后,生成了 B.java 文件:

提取后

Extract interface(提取接口)

顾名思义,就是从这个类中提取出接口。在重构需要抽象时用到。

比如:提取前,A 类下有个 method1 方法。选中 method1 方法,弹出“Extract interface”对话框,填入接口名。

提取前

提取后:

1
2
3
4
5
6
7
8
9
10
11
public interface InterfaceA {
String method1(String arg0, String arg1);
}

public class A implements InterfaceA {

@Override
public String method1(String arg0, String arg1) {
return "hello" + "world";
}
}

Extract Superclass(提取父类)

提取父类和提取接口类似,当我们需要抽象出父类或抽象类时用。

Push Down(下推)

此功能可以将类中的方法和成员从父类中移动到它的子类中,在弹出的对话框中选择哪些方法下推到子类中。下推重构对于重新构建项目设计十分有用。

比如:下推前,B 类继承 A 类,我们可以将 A 类下的 method1 方法下推到 B 类中。

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class A {

protected String helloWorld = "hello" + "world";

public String method1(String arg0, String arg1) {
return helloWorld;
}
}

public class B extends A {

}

下推前

下推后:

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class A {

protected String helloWorld = "hello" + "world";
}

public class B extends A {

public String method1(String arg0, String arg1) {
return helloWorld;
}

}

Push Up(上移)

上移与下推类似,也是在类之间移动方法和成员。上移将方法或成员从一个类移动到它的一个父类中。