详解AndroidStudio中代码重构菜单Refactor功能
代码重构几乎是每个程序员在软件开发中必须要不断去做的事情,以此来不断提高代码的质量。android stido(以下简称as)以其强大的功能,成为当下android开发工程师最受欢迎的开发工具,也是android官方推荐使用的工具。如此优秀的工具,自然少不了要在代码重构这件事情上好好表现一把了。本文将通过代码演示,功能截图来详细介绍as为代码重构提供的各项功能。
在as的主菜单栏中有一项“refactor”下拉菜单,点击该下拉菜单,会看到如下的界面,菜单中的每一项,都是为代码重构提供的一项自动实现功能。这么多的功能项,可见as在代码重构功能上的强大,下面我们对这些功能项一一进行介绍。另外,还可以在编辑界面中点击右键,在弹出的菜单中也可以找到“refactor”。
1、refactor this
作用:重构当前。操作此项,会显示对当前光标选中处可行的重构方法。
示例:选择了类名“refactortest”,操作“refactor this”后,显示了可执行的重构方法列表,可以通过选择数字来执行对应的方法。
2、rename
作用:对光标选中项进行重命名。不仅可以对类中的成员变量进行重命名,还能对文件名,包名等进行重命名,module中与之相关联的所有地方都会一起修改,而不用一一手动修改。
快捷键:shift + f6
示例:在红框中输入修改后的名称,并按enter键即可。
3、rename file
作用:修改当前编辑界面显示的文件的文件名。就相当于鼠标选中该文件,并执行“rename”方法。
示例:在显示的对话框中输入新文件名。可以在下方的选项框中选择修改范围,引用该文件的地方,注释,字符串中都可以选择一起修改。
4、change signature
作用:修改方法、类、构造函数的签名,其实就是修改所选项的一些属性。
快捷键:ctr l+ f6
示例:如下展示了一个方法重构前,重构过程,以及重构后的情形(以修改一个方法签名为例)。
重构前:
private void testchangesignature(int first, int second) { }
选中方法名后,执行该重构方法后,会弹出如下对话框,可以对该方法各种属性进行修改,添加/删除参数,调整参数顺序,新增/删除异常等。
重构后:
public void testchangesignature(int second, int first, string third) throws nullpointerexception { }
5、type migration
作用:类型迁移,即对变量数据类型,或者方法的返回类型进行修改。前面介绍了对文件名,包名,变量名等进行修改,这里对类型进行修改。
快捷键:ctrl + shift + f6
重构前:
private int age = 10; public refactortest(int age) { this.age = age; }
选中要修改的类型,执行该重构方法,会弹出对话框,根据需要编辑类型,选中作用范围即可。指定范围内,与该变量相关联处都会被修改。
重构后(由于从int修改到string,所以还需要手动修改变量值):
private string age = "10"; public refactortest(string age) { this.age = age; }
6、make static
作用:给内部类或者方法添加static关键字。示例比较简单,就不做演示了。
7、convert to instance method
作用: 转换为实例方法,即将静态方法去掉static关键字。
8、move
功能:移动文件到指定路径
快捷键:f6
9、copy
作用:在指定包中拷贝一份当前文件
快捷键:f5
10、safe detele
作用:安全删除,可用于对方法/字段等进行快速删除,会删除掉与之相关联的引用。
快捷键:alt + delete
11、extract
(1)variable
作用:提取变量。这一点在碰到比较长的表达式时经常用到,将看起来很长很复杂的表达式提取出来作为一个变量表示。
快捷键:ctrl + alt + v
重构前:我们常会看到这样的代码
public void testextractvariable() { log.i("demo", "age=" + getaaaaaaaaaaaaaaaaaaaaaaaaaaaage() + ";name=" + getnnnnnnnnnnnnnnnnnnnnnnname()); } private int getaaaaaaaaaaaaaaaaaaaaaaaaaaaage() { return age; } private string getnnnnnnnnnnnnnnnnnnnnnnname() { return name; }
第二行的要打印的信息表达式太长了,希望单独提取出来用一个变量表示。本示例中鼠标停留在第2行“getaaaaaaaaaaaaaaaaaaaaaaaaaaaage”处,执行该重构方法,会弹出如下红框部分对话框,显示的是选中表达式相关的可提取部分,根据需要选择要提取的部分即可。
重构后:
public void testextractvariable() { string msg = "age=" + getaaaaaaaaaaaaaaaaaaaaaaaaaaaage() + ";name=" + getnnnnnnnnnnnnnnnnnnnnnnname(); log.i("demo", msg); } private int getaaaaaaaaaaaaaaaaaaaaaaaaaaaage() { return age; } private string getnnnnnnnnnnnnnnnnnnnnnnname() { return name; }
(2)constant
作用:提取常量,将表达式中的值提取为常量。
快捷键:ctrl + alt +c
重构前:
public void testextractconstant() { string filename = "sdcard"; }
重构后:
public static final string sdcard = "sdcard"; public void testextractconstant() { string filename = sdcard; }
(3)filed
作用:提取字段,将局部变量提取为全局变量。
快捷键:ctrl + alt +f
重构前:
public void testextractfield() { string name ="zhangsan"; }
重构后:
private final string string = "zhangsan"; public void testextractfield() { }
(4)parameter
作用:将局部变量提取为方法的参数。
快捷键:ctrl + alt +p
重构前:
public void testextractparameter() { printname(); } private void printname(){ string name = "zhangsan"; log.i("demo","my name is:"+name); }
重构后:
public void testextractparameter() { printname("zhangsan"); } private void printname(string name){ log.i("demo","my name is:"+ name); }
(5)functional parameter ( 函数式参数 )ctrl + alt + shift + p
(6)parameter object
作用:将参数提取为一个对象。该功能主要是针对参数比较多的时候,将这些参数提取出来作为一个bean实例传入。
重构前:
private void testextractparamobject() { string info = getinfo("zhangshan", 20, 180f); } private string getinfo(string name, int age, float height) { return "name=" + name + ";age=" + age + ";height=" + height; }
重构后:
private void testextractparamobject() { string info = getinfo(new person("zhangshan", 20, 180f)); } private string getinfo(person person) { return "name=" + person.getname() + ";age=" + person.getage() + ";height=" + person.getheight(); } private static class person { private final string name; private final int age; private final float height; private person(string name, int age, float height) { this.name = name; this.age = age; this.height = height; } public string getname() { return name; } public int getage() { return age; } public float getheight() { return height; } }
(7)mehtod
作用:提取为方法
快捷键:ctrl + alt +m
重构前:
public void testextractmethod() { list<string> namelist = new arraylist<>(); namelist.add("zhangshan"); namelist.add("lisi"); namelist.add("wangwu"); int size = namelist.size(); }
鼠标光标选中第2~5行后执行该重构方法
重构后:
public void testextractmethod() { list<string> namelist = getnamelist(); int size = namelist.size(); } @nonnull private list<string> getnamelist() { list<string> namelist = new arraylist<>(); namelist.add("zhangshan"); namelist.add("lisi"); namelist.add("wangwu"); return namelist; }
(8)type parameter
(9)method object
作用:将该选中的内容提取为一个方法,并提取到一个独立的类中。和“method”很类似,不同的是提取的方法最后放在哪里。
重构前:
public void testextractmethod() { list<string> namelist = new arraylist<>(); namelist.add("zhangshan"); namelist.add("lisi"); namelist.add("wangwu"); int size = namelist.size(); }
重构后:
public void testextractmethod() { list<string> namelist = utils.invoke(); int size = namelist.size(); } private static class utils { private static list<string> invoke() { list<string> namelist = new arraylist<>(); namelist.add("zhangshan"); namelist.add("lisi"); namelist.add("wangwu"); return namelist; } }
(10)delegate
作用:提取为一个代理类。
重构前:
public class refactortest{ public void testextractinterface() { system.out.print("testextractinterface"); } }
重构后:
public class refactortestdelegate { public refactortestdelegate() { } public void testextractinterface() { system.out.print("testextractinterface"); } } public class refactortest{ private final refactortestdelegate refactortestdelegate = new refactortestdelegate(); public void testextractinterface() { refactortestdelegate.testextractinterface(); } }
(11)interrface
作用:提取为接口。
重构前:
public class refactortest { public void testextractinterface() { system.out.print("testextractinterface"); } }
public修饰的方法才可以被提取到接口中。
重构后:
interface irefactortest { void testextractinterface(); } public class refactortest implements irefactortest { @override public void testextractinterface() { system.out.print("testextractinterface"); } }
(12)superclass
作用:将指定内容提取到父类中。
重构前:
private void testextractsupperclass() { testsuper(); } public void testsuper() { system.out.print("testsuper"); }
重构后:
//=======refactortest extends refactortestbase======= private void testextractsupperclass() { testsuper(); } class refactortestbase { public void testsuper() { system.out.print("testsuper"); } }
12、inline
作用:转换为内联、方法链形式的调用。
快捷键:ctrl + alt +n
重构前:
private void testinline() { int a = 100; int b = 200; system.out.print(add(a, b)); } private int add(int a, int b) { system.out.print("a=" + a + ";b=" + b); return a*2 + b*3; }
重构后:
private void testinline() { int a = 100; int b = 200; system.out.print("a=" + a + ";b=" + b); system.out.print(a * 2 + b * 3); }
原先需要调用一个方法,重构后直接把该方法中的代码给复制过来了。因为上面选中的是内联所有的,并且删除该方法,所以add方法也就被删除了。
13、find and replace code duplicates
14、invert boolean
作用:转换boolean值,将当前false/true的值进行转化为相反的值。
重构前:
private boolean isempty(string str) { if (str != null && str.length() == 0) { return false; } return true; }
重构后:
private boolean isnotempty(string str) { if (str != null && str.length() == 0) { return true; } return false; }
15、pull members up
作用:将子类的成员上移到父类中。
重构前:
public class refactorbase { } public class rafactorsub extends refactorbase { int age = 10; public void printsub() { system.out.print(age); } }
重构后:
public class refactorbase { int age = 10; public void printsub() { system.out.print(age); } } public class rafactorsub extends refactorbase { }
16、push members down
作用:将父类中的成员下移到子类中,正好是“pull members up”的反向操作。
重构前:
public class refactorbase { int age = 10; public void printsub() { system.out.print(age); } } public class rafactorsub extends refactorbase { }
重构后:
public class refactorbase { } public class rafactorsub extends refactorbase { int age = 10; public void printsub() { system.out.print(age); } }
17、use interface where possible
18、replace inheritance with delegation
作用:使用代理替代继承。在java中,提倡使用组合,而不是继承。
重构前:
public abstract class absclass { public abstract void print(); } public class classwrapper extends absclass { @override public void print() { system.out.print("print"); } } private void testreplaceinheritancewithdelegation() { new classwrapper().print(); }
重构后:
public abstract class absclass { public abstract void print(); } public class classwrapper { private final classimpl absclass = new classimpl(); public void print() { absclass.print(); } private class classimpl extends absclass { @override public void print() { system.out.print("print"); } } } public class refactortest { private void testreplaceinheritancewithdelegation() { new classwrapper().print(); } }
这一部分有点像android中context,contextwrapper,contextimpl类之间的关系。
19、remove middleman
作用:移除中间人,其实就是移除中间过程。
重构前:
public class refactortest { private void testremovemiddleman() { bookmanager bookmanager = new bookmanager(); bookmanager.addbook("java"); } public static class bookmanager { private list<string> mbooklist = new arraylist<>(); private void addbook(string bookname) { mbooklist.add(bookname); } } }
重构后:
public class refactortest { private void testremovemiddleman() { bookmanager bookmanager = new bookmanager(); bookmanager.getmbooklist().add("java"); } public static class bookmanager { private list<string> mbooklist = new arraylist<>(); public list<string> getmbooklist() { return mbooklist; } } }
对比重构前和重构后会发现,添加book这个动作,从由bookmanager的addbook方法来执行,变成了直接有mbooklist来执行了。这个addbook就是这个middleman,显得多余,可以优化掉。实际上优化后就变成一个inline方式了,可以对比前面讲到的“inline”。
20、wrap method return value
作用:封装返回值
public class refactortest { private void testwrapreturnvalue() { string name = getname(); } private string getname() { return "zhangsan"; } }
重构后:
public class refactortest { private void testwrapreturnvalue() { string name = getname().getvalue(); } private person getname() { return new person("zhangsan"); } public class person { private final string value; public person(string value) { this.value = value; } public string getvalue() { return value; } } }
21、convert anonymous to inner
作用:将匿名内部类转为内部类。
重构前:
private void testconvertanonymoustoinner(){ view.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { } }); }
重构后:
public class refactortest{ view view; private void testconvertanonymoustoinner(){ view.setonclicklistener(new myonclicklistener()); } private static class myonclicklistener implements view.onclicklistener { @override public void onclick(view v) { } } }
22、encapsulate fields
作用:封装字段,用于生成getter/setter
重构前:
public string name = "zhangsan"; private void testencapsulatefields() { system.out.println(name); }
通过该对话框,可以选择要封装的字段,设置修饰符等。默认选择时,name字段的修饰符从public变成了private,这也就避免了外部类通过实例直接访问它。
重构后:
private string name = "zhangsan"; private void testencapsulatefields() { system.out.println(getname()); } public string getname() { return name; } public void setname(string name) { this.name = name; }
23、replace temp with query
24、replace constructor with factory method
作用:将构造方法替换为工厂方法
重构前:
public class myclass { private string title; private string message; private string sure; private string cancel; public myclass(string title, string message, string sure, string cancel) { this.title = title; this.message = message; this.sure = sure; this.cancel = cancel; } } public class refactortest { private void testreplaceconstructorwithfactory(context context) { myclass myclass = new myclass("title", "message", "sure", "cancle"); } }
重构后:
public class myclass { private string title; private string message; private string sure; private string cancel; private myclass(string title, string message, string sure, string cancel) { this.title = title; this.message = message; this.sure = sure; this.cancel = cancel; } public static myclass createmyclass(string title, string message, string sure, string cancel) { return new myclass(title, message, sure, cancel); } } public class refactortest { private void testreplaceconstructorwithfactory(context context) { myclass myclass = myclass.createmyclass("title", "message", "sure", "cancle"); } }
原先public修饰的构造函数,已经变成private了,myclass类只能通过工厂方法来获取实例,而无法再直接new了。
25、replace constructor with builder
作用:将构造方法替换为builder方式
重构前:
public class refactortest{ private void testreplaceconstructorwithbuilder(context context){ mydialog dialog = new mydialog(context,"title","message","sure","cancle"); } } public class mydialog extends dialog { private string title; private string message; private string sure; private string cancel; public mydialog(@nonnull context context) { super(context); } public mydialog(context context, string title, string message, string sure, string cancel) { super(context); this.title = title; this.message = message; this.sure = sure; this.cancel = cancel; } }
重构后:
public class refactortest { private void testreplaceconstructorwithbuilder(context context) { mydialog dialog = new mydialogbuilder() .setcontext(context) .settitle("title") .setmessage("message") .setsure("sure") .setcancel("cancle") .createmydialog(); } } public class mydialogbuilder { private context context; private string title; private string message; private string sure; private string cancel; public mydialogbuilder setcontext(context context) { this.context = context; return this; } public mydialogbuilder settitle(string title) { this.title = title; return this; } public mydialogbuilder setmessage(string message) { this.message = message; return this; } public mydialogbuilder setsure(string sure) { this.sure = sure; return this; } public mydialogbuilder setcancel(string cancel) { this.cancel = cancel; return this; } public mydialog createmydialog() { return new mydialog(context); } }
看到这里,我们应该能够联想到alertdialog类中的builder了。将构造函数的形式,转变为了建造者模式的形式,这样不会拘泥于构造函数的参数个数,参数类型的限制,从而灵活设置属性。
26、generify
作用:泛型重构,自动添加泛型的参数。
重构前:
private void testgenerify() { list list = new arraylist(); list.add("one"); list.add("two"); list.add("three"); }
重构后:
private void testgenerify() { list<string> list = new arraylist<string>(); list.add("one"); list.add("two"); list.add("three"); }
27、migrate
28、internationalize(国际化)
29、remove unused resources
作用:一直不用的资源
示例:下图中1.jpg是一个没有被应用的文件。
在执行该重构方法后,1.jpg就被删除了。
总结
以上所述是小编给大家介绍的androidstudio中代码重构菜单refactor功能,希望对大家有所帮助