详解AndroidStudio中代码重构菜单Refactor功能
代码重构几乎是每个程序员在软件开发中必须要不断去做的事情,以此来不断提高代码的质量。AndroidStido(以下简称AS)以其强大的功能,成为当下Android开发工程师最受欢迎的开发工具,也是Android官方推荐使用的工具。如此优秀的工具,自然少不了要在代码重构这件事情上好好表现一把了。本文将通过代码演示,功能截图来详细介绍AS为代码重构提供的各项功能。
在AS的主菜单栏中有一项“Refactor”下拉菜单,点击该下拉菜单,会看到如下的界面,菜单中的每一项,都是为代码重构提供的一项自动实现功能。这么多的功能项,可见AS在代码重构功能上的强大,下面我们对这些功能项一一进行介绍。另外,还可以在编辑界面中点击右键,在弹出的菜单中也可以找到“Refactor”。
1、RefactorThis
作用:重构当前。操作此项,会显示对当前光标选中处可行的重构方法。
示例:选择了类名“RefactorTest”,操作“RefactorThis”后,显示了可执行的重构方法列表,可以通过选择数字来执行对应的方法。
2、Rename
作用:对光标选中项进行重命名。不仅可以对类中的成员变量进行重命名,还能对文件名,包名等进行重命名,Module中与之相关联的所有地方都会一起修改,而不用一一手动修改。
快捷键:Shift+F6
示例:在红框中输入修改后的名称,并按Enter键即可。
3、RenameFile
作用:修改当前编辑界面显示的文件的文件名。就相当于鼠标选中该文件,并执行“Rename”方法。
示例:在显示的对话框中输入新文件名。可以在下方的选项框中选择修改范围,引用该文件的地方,注释,字符串中都可以选择一起修改。
4、ChangeSignature
作用:修改方法、类、构造函数的签名,其实就是修改所选项的一些属性。
快捷键:Ctrl+F6
示例:如下展示了一个方法重构前,重构过程,以及重构后的情形(以修改一个方法签名为例)。
重构前:
privatevoidtestChangeSignature(intfirst,intsecond){ }
选中方法名后,执行该重构方法后,会弹出如下对话框,可以对该方法各种属性进行修改,添加/删除参数,调整参数顺序,新增/删除异常等。
重构后:
publicvoidtestChangeSignature(intsecond,intfirst,Stringthird)throwsNullPointerException{ }
5、TypeMigration
作用:类型迁移,即对变量数据类型,或者方法的返回类型进行修改。前面介绍了对文件名,包名,变量名等进行修改,这里对类型进行修改。
快捷键:Ctrl+Shift+F6
重构前:
privateintage=10; publicRefactorTest(intage){ this.age=age; }
选中要修改的类型,执行该重构方法,会弹出对话框,根据需要编辑类型,选中作用范围即可。指定范围内,与该变量相关联处都会被修改。
重构后(由于从int修改到String,所以还需要手动修改变量值):
privateStringage="10"; publicRefactorTest(Stringage){ this.age=age; }
6、MakeStatic
作用:给内部类或者方法添加static关键字。示例比较简单,就不做演示了。
7、ConvertToInstanceMethod
作用:转换为实例方法,即将静态方法去掉static关键字。
8、Move
功能:移动文件到指定路径
快捷键:F6
9、Copy
作用:在指定包中拷贝一份当前文件
快捷键:F5
10、SafeDetele
作用:安全删除,可用于对方法/字段等进行快速删除,会删除掉与之相关联的引用。
快捷键:Alt+Delete
11、Extract
(1)Variable
作用:提取变量。这一点在碰到比较长的表达式时经常用到,将看起来很长很复杂的表达式提取出来作为一个变量表示。
快捷键:Ctrl+Alt+V
重构前:我们常会看到这样的代码
publicvoidtestExtractVariable(){ Log.i("demo","age="+getAaaaaaaaaaaaaaaaaaaaaaaaaaaAge()+";name="+getNnnnnnnnnnnnnnnnnnnnnnname()); } privateintgetAaaaaaaaaaaaaaaaaaaaaaaaaaaAge(){ returnage; } privateStringgetNnnnnnnnnnnnnnnnnnnnnnname(){ returnname; }
第二行的要打印的信息表达式太长了,希望单独提取出来用一个变量表示。本示例中鼠标停留在第2行“getAaaaaaaaaaaaaaaaaaaaaaaaaaaAge”处,执行该重构方法,会弹出如下红框部分对话框,显示的是选中表达式相关的可提取部分,根据需要选择要提取的部分即可。
重构后:
publicvoidtestExtractVariable(){ Stringmsg="age="+getAaaaaaaaaaaaaaaaaaaaaaaaaaaAge()+";name="+getNnnnnnnnnnnnnnnnnnnnnnname(); Log.i("demo",msg); } privateintgetAaaaaaaaaaaaaaaaaaaaaaaaaaaAge(){ returnage; } privateStringgetNnnnnnnnnnnnnnnnnnnnnnname(){ returnname; }
(2)Constant
作用:提取常量,将表达式中的值提取为常量。
快捷键:Ctrl+Alt+C
重构前:
publicvoidtestExtractConstant(){ Stringfilename="sdcard"; }
重构后:
publicstaticfinalStringSDCARD="sdcard"; publicvoidtestExtractConstant(){ Stringfilename=SDCARD; }
(3)Filed
作用:提取字段,将局部变量提取为全局变量。
快捷键:Ctrl+Alt+F
重构前:
publicvoidtestExtractField(){ Stringname="zhangsan"; }
重构后:
privatefinalStringstring="zhangsan"; publicvoidtestExtractField(){ }
(4)Parameter
作用:将局部变量提取为方法的参数。
快捷键:Ctrl+Alt+P
重构前:
publicvoidtestExtractParameter(){ printName(); } privatevoidprintName(){ Stringname="zhangsan"; Log.i("demo","Mynameis:"+name); }
重构后:
publicvoidtestExtractParameter(){ printName("zhangsan"); } privatevoidprintName(Stringname){ Log.i("demo","Mynameis:"+name); }
(5)FunctionalParameter(函数式参数)Ctrl+Alt+Shift+P
(6)ParameterObject
作用:将参数提取为一个对象。该功能主要是针对参数比较多的时候,将这些参数提取出来作为一个Bean实例传入。
重构前:
privatevoidtestExtractParamObject(){ Stringinfo=getInfo("zhangshan",20,180f); } privateStringgetInfo(Stringname,intage,floatheight){ return"name="+name+";age="+age+";height="+height; }
重构后:
privatevoidtestExtractParamObject(){ Stringinfo=getInfo(newPerson("zhangshan",20,180f)); } privateStringgetInfo(Personperson){ return"name="+person.getName()+";age="+person.getAge()+";height="+person.getHeight(); } privatestaticclassPerson{ privatefinalStringname; privatefinalintage; privatefinalfloatheight; privatePerson(Stringname,intage,floatheight){ this.name=name; this.age=age; this.height=height; } publicStringgetName(){ returnname; } publicintgetAge(){ returnage; } publicfloatgetHeight(){ returnheight; } }
(7)Mehtod
作用:提取为方法
快捷键:Ctrl+Alt+M
重构前:
publicvoidtestExtractMethod(){ ListnameList=newArrayList<>(); nameList.add("zhangshan"); nameList.add("lisi"); nameList.add("wangwu"); intsize=nameList.size(); }
鼠标光标选中第2~5行后执行该重构方法
重构后:
publicvoidtestExtractMethod(){ ListnameList=getNameList(); intsize=nameList.size(); } @NonNull privateList getNameList(){ List nameList=newArrayList<>(); nameList.add("zhangshan"); nameList.add("lisi"); nameList.add("wangwu"); returnnameList; }
(8)TypeParameter
(9)MethodObject
作用:将该选中的内容提取为一个方法,并提取到一个独立的类中。和“Method”很类似,不同的是提取的方法最后放在哪里。
重构前:
publicvoidtestExtractMethod(){ ListnameList=newArrayList<>(); nameList.add("zhangshan"); nameList.add("lisi"); nameList.add("wangwu"); intsize=nameList.size(); }
重构后:
publicvoidtestExtractMethod(){ ListnameList=Utils.invoke(); intsize=nameList.size(); } privatestaticclassUtils{ privatestaticList invoke(){ List nameList=newArrayList<>(); nameList.add("zhangshan"); nameList.add("lisi"); nameList.add("wangwu"); returnnameList; } }
(10)Delegate
作用:提取为一个代理类。
重构前:
publicclassRefactorTest{ publicvoidtestExtractInterface(){ System.out.print("testExtractInterface"); } }
重构后:
publicclassRefactorTestDelegate{ publicRefactorTestDelegate(){ } publicvoidtestExtractInterface(){ System.out.print("testExtractInterface"); } } publicclassRefactorTest{ privatefinalRefactorTestDelegaterefactorTestDelegate=newRefactorTestDelegate(); publicvoidtestExtractInterface(){ refactorTestDelegate.testExtractInterface(); } }
(11)Interrface
作用:提取为接口。
重构前:
publicclassRefactorTest{ publicvoidtestExtractInterface(){ System.out.print("testExtractInterface"); } }
public修饰的方法才可以被提取到接口中。
重构后:
interfaceIRefactorTest{ voidtestExtractInterface(); } publicclassRefactorTestimplementsIRefactorTest{ @Override publicvoidtestExtractInterface(){ System.out.print("testExtractInterface"); } }
(12)Superclass
作用:将指定内容提取到父类中。
重构前:
privatevoidtestExtractSupperclass(){ testSuper(); } publicvoidtestSuper(){ System.out.print("testSuper"); }
重构后:
//=======RefactorTestextendsRefactorTestBase======= privatevoidtestExtractSupperclass(){ testSuper(); } classRefactorTestBase{ publicvoidtestSuper(){ System.out.print("testSuper"); } }
12、Inline
作用:转换为内联、方法链形式的调用。
快捷键:Ctrl+Alt+N
重构前:
privatevoidtestInline(){ inta=100; intb=200; System.out.print(add(a,b)); } privateintadd(inta,intb){ System.out.print("a="+a+";b="+b); returna*2+b*3; }
重构后:
privatevoidtestInline(){ inta=100; intb=200; System.out.print("a="+a+";b="+b); System.out.print(a*2+b*3); }
原先需要调用一个方法,重构后直接把该方法中的代码给复制过来了。因为上面选中的是内联所有的,并且删除该方法,所以add方法也就被删除了。
13、FindandReplaceCodeDuplicates
14、InvertBoolean
作用:转换Boolean值,将当前false/true的值进行转化为相反的值。
重构前:
privatebooleanisEmpty(Stringstr){ if(str!=null&&str.length()==0){ returnfalse; } returntrue; }
重构后:
privatebooleanisNotEmpty(Stringstr){ if(str!=null&&str.length()==0){ returntrue; } returnfalse; }
15、PullMembersUp
作用:将子类的成员上移到父类中。
重构前:
publicclassRefactorBase{ } publicclassRafactorSubextendsRefactorBase{ intage=10; publicvoidprintSub(){ System.out.print(age); } }
重构后:
publicclassRefactorBase{ intage=10; publicvoidprintSub(){ System.out.print(age); } } publicclassRafactorSubextendsRefactorBase{ }
16、PushMembersDown
作用:将父类中的成员下移到子类中,正好是“PullMembersUp”的反向操作。
重构前:
publicclassRefactorBase{ intage=10; publicvoidprintSub(){ System.out.print(age); } } publicclassRafactorSubextendsRefactorBase{ }
重构后:
publicclassRefactorBase{ } publicclassRafactorSubextendsRefactorBase{ intage=10; publicvoidprintSub(){ System.out.print(age); } }
17、UseInterfaceWherePossible
18、ReplaceInheritancewithDelegation
作用:使用代理替代继承。在java中,提倡使用组合,而不是继承。
重构前:
publicabstractclassAbsClass{ publicabstractvoidprint(); } publicclassClassWrapperextendsAbsClass{ @Override publicvoidprint(){ System.out.print("print"); } } privatevoidtestReplaceInheritanceWithDelegation(){ newClassWrapper().print(); }
重构后:
publicabstractclassAbsClass{ publicabstractvoidprint(); } publicclassClassWrapper{ privatefinalClassImplabsClass=newClassImpl(); publicvoidprint(){ absClass.print(); } privateclassClassImplextendsAbsClass{ @Override publicvoidprint(){ System.out.print("print"); } } } publicclassRefactorTest{ privatevoidtestReplaceInheritanceWithDelegation(){ newClassWrapper().print(); } }
这一部分有点像Android中Context,ContextWrapper,ContextImpl类之间的关系。
19、RemoveMiddleman
作用:移除中间人,其实就是移除中间过程。
重构前:
publicclassRefactorTest{ privatevoidtestRemoveMiddleMan(){ BookManagerbookManager=newBookManager(); bookManager.addBook("java"); } publicstaticclassBookManager{ privateListmBookList=newArrayList<>(); privatevoidaddBook(StringbookName){ mBookList.add(bookName); } } }
重构后:
publicclassRefactorTest{ privatevoidtestRemoveMiddleMan(){ BookManagerbookManager=newBookManager(); bookManager.getmBookList().add("java"); } publicstaticclassBookManager{ privateListmBookList=newArrayList<>(); publicList getmBookList(){ returnmBookList; } } }
对比重构前和重构后会发现,添加book这个动作,从由BookManager的addBook方法来执行,变成了直接有mBookList来执行了。这个addBook就是这个MiddleMan,显得多余,可以优化掉。实际上优化后就变成一个inline方式了,可以对比前面讲到的“Inline”。
20、WrapMethodReturnValue
作用:封装返回值
publicclassRefactorTest{ privatevoidtestWrapReturnValue(){ Stringname=getName(); } privateStringgetName(){ return"zhangsan"; } }
重构后:
publicclassRefactorTest{ privatevoidtestWrapReturnValue(){ Stringname=getName().getValue(); } privatePersongetName(){ returnnewPerson("zhangsan"); } publicclassPerson{ privatefinalStringvalue; publicPerson(Stringvalue){ this.value=value; } publicStringgetValue(){ returnvalue; } } }
21、ConvertAnonymoustoInner
作用:将匿名内部类转为内部类。
重构前:
privatevoidtestConvertAnonymousToInner(){ view.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ } }); }
重构后:
publicclassRefactorTest{ Viewview; privatevoidtestConvertAnonymousToInner(){ view.setOnClickListener(newMyOnClickListener()); } privatestaticclassMyOnClickListenerimplementsView.OnClickListener{ @Override publicvoidonClick(Viewv){ } } }
22、EncapsulateFields
作用:封装字段,用于生成Getter/Setter
重构前:
publicStringname="zhangsan"; privatevoidtestEncapsulateFields(){ System.out.println(name); }
通过该对话框,可以选择要封装的字段,设置修饰符等。默认选择时,name字段的修饰符从public变成了private,这也就避免了外部类通过实例直接访问它。
重构后:
privateStringname="zhangsan"; privatevoidtestEncapsulateFields(){ System.out.println(getName()); } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; }
23、ReplaceTempWithQuery
24、ReplaceConstructorwithFactoryMethod
作用:将构造方法替换为工厂方法
重构前:
publicclassMyClass{ privateStringtitle; privateStringmessage; privateStringsure; privateStringcancel; publicMyClass(Stringtitle,Stringmessage,Stringsure,Stringcancel){ this.title=title; this.message=message; this.sure=sure; this.cancel=cancel; } } publicclassRefactorTest{ privatevoidtestReplaceConstructorWithFactory(Contextcontext){ MyClassmyClass=newMyClass("title","message","sure","cancle"); } }
重构后:
publicclassMyClass{ privateStringtitle; privateStringmessage; privateStringsure; privateStringcancel; privateMyClass(Stringtitle,Stringmessage,Stringsure,Stringcancel){ this.title=title; this.message=message; this.sure=sure; this.cancel=cancel; } publicstaticMyClasscreateMyClass(Stringtitle,Stringmessage,Stringsure,Stringcancel){ returnnewMyClass(title,message,sure,cancel); } } publicclassRefactorTest{ privatevoidtestReplaceConstructorWithFactory(Contextcontext){ MyClassmyClass=MyClass.createMyClass("title","message","sure","cancle"); } }
原先public修饰的构造函数,已经变成private了,MyClass类只能通过工厂方法来获取实例,而无法再直接new了。
25、ReplaceConstructorwithBuilder
作用:将构造方法替换为Builder方式
重构前:
publicclassRefactorTest{ privatevoidtestReplaceConstructorWithBuilder(Contextcontext){ MyDialogdialog=newMyDialog(context,"title","message","sure","cancle"); } } publicclassMyDialogextendsDialog{ privateStringtitle; privateStringmessage; privateStringsure; privateStringcancel; publicMyDialog(@NonNullContextcontext){ super(context); } publicMyDialog(Contextcontext,Stringtitle,Stringmessage,Stringsure,Stringcancel){ super(context); this.title=title; this.message=message; this.sure=sure; this.cancel=cancel; } }
重构后:
publicclassRefactorTest{ privatevoidtestReplaceConstructorWithBuilder(Contextcontext){ MyDialogdialog=newMyDialogBuilder() .setContext(context) .setTitle("title") .setMessage("message") .setSure("sure") .setCancel("cancle") .createMyDialog(); } } publicclassMyDialogBuilder{ privateContextcontext; privateStringtitle; privateStringmessage; privateStringsure; privateStringcancel; publicMyDialogBuildersetContext(Contextcontext){ this.context=context; returnthis; } publicMyDialogBuildersetTitle(Stringtitle){ this.title=title; returnthis; } publicMyDialogBuildersetMessage(Stringmessage){ this.message=message; returnthis; } publicMyDialogBuildersetSure(Stringsure){ this.sure=sure; returnthis; } publicMyDialogBuildersetCancel(Stringcancel){ this.cancel=cancel; returnthis; } publicMyDialogcreateMyDialog(){ returnnewMyDialog(context); } }
看到这里,我们应该能够联想到AlertDialog类中的Builder了。将构造函数的形式,转变为了建造者模式的形式,这样不会拘泥于构造函数的参数个数,参数类型的限制,从而灵活设置属性。
26、Generify
作用:泛型重构,自动添加泛型的参数。
重构前:
privatevoidtestGenerify(){ Listlist=newArrayList(); list.add("one"); list.add("two"); list.add("three"); }
重构后:
privatevoidtestGenerify(){ Listlist=newArrayList (); list.add("one"); list.add("two"); list.add("three"); }
27、Migrate
28、Internationalize(国际化)
29、RemoveUnusedResources
作用:一直不用的资源
示例:下图中1.jpg是一个没有被应用的文件。
在执行该重构方法后,1.jpg就被删除了。
总结
以上所述是小编给大家介绍的AndroidStudio中代码重构菜单Refactor功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。