安全类规则


1. 用SharedPreference来保存数据时,涉及敏感信息的key在命名时需使用缩写或者其他不易知其意的命名。

级别:Block

描述:用SharedPreference来保存数据时,涉及敏感信息的key在命名时需使用缩写或者其他不易知其意的命名,比如:KEY_PHONENUMBER, KEY_SERVER_IP_ADDRESS,应该改为KEY_P_N, KEY_S_I_A等。

代码示例:

                                                   
                            SharedPreferences sharedPreferences=getSharedPreferences("ljq123", 
                            Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
                            Editor editor = sharedPreferences.edit();
                            editor.putInt("KEY_PHONENUMBER", age);//触发规则
                            editor.putString("KEY_SERVER_IP_ADDRESS", age);//触发规则
                             
                        

推荐写法:

                                                   
                            SharedPreferences sharedPreferences=getSharedPreferences("ljq123", 
                            Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
                            Editor editor = sharedPreferences.edit();
                            editor.putInt("K_P_N", age);
                            editor.putString("K_S_A", age);
                             
                        
2. 正确使用Content Provider的openFile函数,防止造成目录遍历漏洞

级别:Block

描述:如果扫描到应用provider组件导出,且没有做权限限制,组件重写了ContentProvider.openFile()函数,却没有调用File.getCanonicalPath()函数进行过滤,存在安全隐患。

代码示例:

                            
                            //目录遍历漏洞程序代码片段1:
                            private static String IMAGE_DIRECTORY = localFile.getAbsolutePath();
                            public ParcelFileDescriptor openFile(Uri paramUri, String paramString) throws FileNotFoundException {
                            	File file = new File(IMAGE_DIRECTORY, paramUri.getLastPathSegment());  //触发规则
                            	return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
                            }
                            //目录遍历漏洞程序代码片段2:
                            private static String IMAGE_DIRECTORY = localFile.getAbsolutePath();
                            public ParcelFileDescriptor openFile(Uri paramUri, String paramString) throws FileNotFoundException {
                            	File file = new File(IMAGE_DIRECTORY, Uri.parse(paramUri.getLastPathSegment()).getLastPathSegment());  //触发规则
                            	return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
                            }
                             
                        

推荐写法:

                               
                            //首先对paramUri解码,文件创建后再通过调用File.getCanonicalPath()来对path的格式进行规范化,最后校验其是否在预定义的目录IMAGE_DIRECTORY
                            private static String IMAGE_DIRECTORY = localFile.getAbsolutePath();
                            public ParcelFileDescriptor openFile(Uri paramUri, String paramString) throws FileNotFoundException {
                            	String decodedUriString = Uri.decode(paramUri.toString());
                            	File file = new File(IMAGE_DIRECTORY, Uri.parse(decodedUriString).getLastPathSegment());
                            	if (file.getCanonicalPath().indexOf(localFile.getCanonicalPath()) != 0) {
                            		throw new IllegalArgumentException();
                            	}
                            	return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
                            } 
                             
                        
3. 不合理的Activity组件导出会导致拒绝服务

级别:Block

描述:如果Intent在使用时未做异常处理,并且该intent所在的activity组件被设置为导出,且没有对调用者身份进行判断或访问权限控制,这种情况下会导致拒绝服务。

代码示例:

                                                   
                            @Override
                            protected void onCreate(Bundle savedInstanceState) {
                                super.onCreate(savedInstanceState);
                                setContentView(R.layout.activity_main);
                                
                                Intent i = getIntent();
                                String url = i.getStringExtra("url");//触发规则
                                
                            } 
                            
                            //同时AndroidManifest.xml文件中的该activity组件设置为导出
                            <activity
                                android:name="com.qihoo.test.activity.TestActivity"                                  
                                android:exported="true">                                
                            </activity>
                             
                             
                        

推荐写法:

                                                   
                            @Override
                            protected void onCreate(Bundle savedInstanceState) {
                                super.onCreate(savedInstanceState);
                                setContentView(R.layout.activity_main);
                                try{
                                   Intent i = getIntent();
                                   String url = i.getStringExtra("url");//触发规则
                                }catch{
                                    //捕获异常做自定义处理
                                }
                            }
                            
                            //AndroidManifest.xml中不需要导出的组件设置为不可导出。当组件需要导出时,进行权限验证或者身份判断。
                            <activity
                                android:name="com.qihoo.test.activity.TestActivity"                                  
                                android:exported="false">                                
                            </activity>
                             
                             
                        
4. AndroidManifest.xml文件中组件导出过多,可能导致敏感界面被独立启动造成越权绕过

级别:风险

描述:AndroidManifest.xml文件中activity组件导出过多,可能会允许一个恶意的其他应用越权启动这个Activity获取此应用的敏感信息、修改内部的应用状态、通过导出的组件直接启动Activity有可能跳过APP的正常的业务逻辑给公司或者是用户造成潜在的损失。

代码示例:

                                                   
                                
                                <activity
                                    android:name="com.qihoo.test.activity.TestActivity"                                  
                                    android:exported="true">                                
                                </activity> 
                                <activity
                                    android:name="com.qihoo.test.activity.Test1Activity"                                  
                                    android:exported="true">                                
                                </activity>
                                <activity
                                    android:name="com.qihoo.test.activity.Test2Activity"                                  
                                    android:exported="true">                                
                                </activity>
                                 
                             
                        

推荐写法:

                            
                            不应该导出的组件严禁导出,导出的Activity要做好安全限制,不要提供过于强大的功能,导致黑客可以利用组件的原有功能进行恶意操作,或使用超出原有功能的溢出或二次攻击。
                             
                        
5. 应用使用了Intent.parseUri(),且没有严格过滤,可能导致远程拒绝服务、远程提权等攻击

级别:Block

描述:Android的Activity通过intent进行应用内部或应用之间的数据传输,如果组件没有正确的处理数据来源,可能会导致安全问题。

代码示例:

                                                   
                            Uri uri  = getIntent().getData();
                            Intent intent = Intent.parseUri(uri);//触发规则
                             
                        

推荐写法:

                                                   
                            Uri uri  = getIntent().getData();
                            Intent intent = Intent.parseUri(uri);
                            intent.addCategory("android.intent.category.BROWSABLE");//如果调用该方法的组件没有对外暴露,可以忽略该设置。
                            intent.setComponent(null);
                            intent.setSelector(null);
                             
                        
6. sql注入风险

级别:风险

描述:对Content Provider进行增删改查操作时,程序没有对用户的输入进行过滤,未采用参数化查询的方式,可能导致sql注入攻击。

代码示例:

                                                   
                            private SQLiteDatabase db;
                            db.rawQuery("select * from person", null);//触发规则
                             
                        

推荐写法:

                        	
                            1.服务端充分校验参数
                            2.使用参数化查询,比如SQLiteStatement
                            3.避免使用rawQuery()方法
                            4.对用户输入进行过滤
                            
                            //例如可使用以下方式:
                            SQLiteStatement sqLiteStatement = db.compileStatement("insert into msgTable(uid, msg) values(?, ?)");
                            sqLiteStatement.bindLong(1, 12);
                            sqLiteStatement.bindString(3, "text");
                            long newRowId = sqLiteStatement.executeInsert();
                            

                        
7. WebView未禁止访问本地文件系统

级别:Block

描述:使用Webview的时候需要将setAllowFileAccess()和setJavaScriptEnabled()置为false来禁止文件系统访问,禁止对JavaScript的支持。最好统一规范,提供CommonWebView进行控制。

代码示例:

                                                   
                            public class TestWebViewRule extends Activity {
                                private WebView webview;
                                @Override
                                public void onCreate(Bundle savedInstanceState) {
                                    super.onCreate(savedInstanceState);
                                    setContentView(R.layout.main);
                                    webview = (WebView) findViewById(R.id.webview);
                                    //设置WebView属性,能够执行Javascript脚本  
                                    webview.getSettings().setJavaScriptEnabled(true);//触发规则
                                    webview.getSettings().setAllowFileAccess(true);//触发规则
                                    //加载需要显示的网页  
                                    webview.loadUrl("http://www.so.com/");
                                    //设置Web视图  
                                    webview.setWebViewClient(new HelloWebViewClient ());
                                }
                            }    
                             
                        

推荐写法:

                            1.限制最小SDK版本大于等于17
                            2.使用安全类,写法见这里:https://github.com/0xr0ot/SafeWebView
                            3.显式设置setSavePassword()为false。
                            4.显式设置setAllowUniversalAccessFromFileURLs()为false。
                            5.显式设置setAllowFileAccessFromFileURLs()为false。
                            6.显式设置setAllowContentAccess()为false。
                            7.显式设置setAllowFileAccess()为fasle。 
                        
8. protectionLevel权限等级使用不正确,会降低程序安全性

级别:建议

描述:自定义权限时使用protectionLevel的默认值或显示设置为normal,会导致权限泄露。对于敏感权限建议设置为signature或者signatureOrSystem。

代码示例:

                                                   
                            
                            <permission 
                            	android:description="string resource" 
                            	android:icon="drawable resource"
                            	android:label="string resource" 
                            	android:name="string" 
                            	android:permissionGroup="string" 
                            	android:protectionLevel="normal" //触发规则 >
                            </permission>
                                                       
                             
                        

推荐写法:

                                                   
                            
                            <permission
                            	android:description="string resource"
                            	android:icon="drawable resource"
                            	android:label="string resource"
                            	android:name="string"
                            	android:permissionGroup="string"
                            	android:protectionLevel="signature" > 
                            </permission>
                             
                             
                        
9. AndroidMannifest.xml文件中android:allowBackup属性设置为true时会导致数据泄露

级别:风险

描述:建议将AndroidMannifest.xml文件android:allowBackup属性设置为false。当allowBackup未设置值(默认值为true)或者标志值为true时,攻击者可通过adb backup和adb restore来备份和恢复应用程序数据。

推荐写法:

                                                   
                            1.minSdkVersion不低于9。
                            2.android:allowBackup属性显示设置为false。
                             
                        
10. AndroidMannifest.xml文件中android:debuggable设置为true时会导致APP被恶意攻击者控制

级别:风险

描述:建议将AndroidMannifest.xml文件android:debuggable属性设置为false。当debuggable标志值为true时,该程序可被任意调试,导致APP被恶意攻击者控制。

推荐写法:

                                                   
                            1.android:debuggable属性显示设置为false。
                             
                        
11. 导出的Activity继承PreferenceActivity,且未重写PreferenceActivity.isValidFragment方法,可能导致Fragment注入漏洞

级别:Block

描述:导出的Activity继承PreferenceActivity,且Activity里未重写 PreferenceActivity.isValidFragment方法,这将会导致受害者应用敏感数据泄露、权限被滥用、拒绝服务、代码执行等。

代码示例:

                        	
                        	@Override
                        	protected void onCreate(Bundle savedInstanceState) {
                        		super.onCreate(savedInstanceState);
                        		String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
                        		Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);

                        		if (savedInstanceState != null) {
                        		...
                        		} else {
                        			if (initialFragment != null && mSinglePane) {
                        				switchToHeader(initialFragment, initialArguments);
                        				} else {
                        					if (mHeaders.size() > 0) {
                        						if (!mSinglePane) {
                        							if (initialFragment == null) {
                        							...
                        							} else {
                        								switchToHeader(initialFragment, initialArguments);
                        							}
                        						}
                        					}
                        				}
                        			}
                        		}

                        	public void switchToHeader(String fragmentName, Bundle args) {
                        		setSelectedHeader(null);
                        		switchToHeaderInner(fragmentName, args, 0);
                        	}

                        	private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {  //触发规则
                        		getFragmentManager().popBackStack(BACK_STACK_PREFS,FragmentManager.POP_BACK_STACK_INCLUSIVE);
                        		Fragment f = Fragment.instantiate(this, fragmentName, args);
                        		FragmentTransaction transaction = getFragmentManager().beginTransaction();
                        		transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                        		transaction.replace(com.android.internal.R.id.prefs, f);
                        		transaction.commitAllowingStateLoss();
                        	}

                        	//Fragment.instantiate实现:
                        	public static Fragment instantiate(Context context, String fname, Bundle args) {
                        		try {
                        			Class clazz = sClassMap.get(fname);
                        			if (clazz == null) {
                        				clazz = context.getClassLoader().loadClass(fname);
                        				sClassMap.put(fname, clazz);
                        			}

                        			Fragment f = (Fragment)clazz.newInstance();
                        			if (args != null) {
                        				args.setClassLoader(f.getClass().getClassLoader());
                        				f.mArguments = args;
                        			}
                        			return f;
                        		}
                        		...
                        	}
                        	
                        

推荐写法:

                                                   
                            //如果一定要使用PreferenceActivity,那么android:minSdkVersion>= 19,然后重写 PreferenceActivity.isValidFragment方法,验证Fragment来源正确性。
                            private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
                            	getFragmentManager().popBackStack(BACK_STACK_PREFS,FragmentManager.POP_BACK_STACK_INCLUSIVE);
                            	if (!isValidFragment(fragmentName)) {
                            		throw new IllegalArgumentException("Invalid fragment for this activity: "+ fragmentName);
                            	}
                            	Fragment f = Fragment.instantiate(this, fragmentName, args);
                            	FragmentTransaction transaction = getFragmentManager().beginTransaction();
                            	transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                            	transaction.replace(com.android.internal.R.id.prefs, f);
                            	transaction.commitAllowingStateLoss();
                            }
                             
                        

日志类规则


1. Log中不要输出敏感信息,例如pid、uid、imei号等

级别:Block

描述:Log中不要输出敏感信息,例如pid、uid、imei号等(不同公司要求不同,视情况定)。

代码示例:

                                                   
                            int pid= android.os.Process.myPid();
                            Log.i("pid", pid);//触发规则
                            Log.i("Name:", getLocalClassName());//触发规则
                            Log.i("imei:", imei.toString());//触发规则
                             
                        

推荐写法:

                            1.不要在代码中输出敏感信息
                            2.如果不得不,请使用开关项进行关闭,比如DEBUG开关,比如:
                            public class Constant {
                                public static final boolean LOGD_ENABLED = BuildConfig.DEBUG;
                                public static final boolean LOGE_ENABLED = BuildConfig.DEBUG;
                            } //注意上述代码类型为boolean而不是Boolean,因为编译器会将开关控制区域内的代码去掉。但是只对原始数据类型的开关起作用。
                            3.或者在编译的时候通过proguard进行函数过滤。
                        
2. 不要在Log方法中对变量进行赋值操作

级别:建议

描述:不要在Log方法中对变量进行赋值操作(部分业务适用)。

代码示例:

                                                   
                            Log.info("a: " + a++);//触发规则
                            Log.info("b1: " + (b1=a));//触发规则
                             
                        
3. 建议使用if(DEBUG)包裹Log方法,日志开关不要封装在日志所在的函数中

级别:建议

描述:建议使用if(DEBUG)包裹Log方法,日志开关不要封装在日志所在的函数中。

代码示例:

                                                   
                            public class checklogwarning{
                                public static void main(String []args){     
                                    Logger Log = Logger.getLogger("log");
                                    boolean DEBUG = true;  //开关不用定义在函数内部                                         
                                    int a=1;
                                    int b1;
                                    if (DEBUG) {
                                        Log.info("a: " + a);//触发规则   
                                    }       
                                        Log.info("a: " + a);//触发规则      
                                }
                            }
                             
                        

推荐写法:

                                                   
                            public class checklogwarning{
                                boolean DEBUG = true;
                                public static void main(String []args){     
                                    Logger Log = Logger.getLogger("log");                                     
                                    int a=1;
                                    int b1;
                                    if (DEBUG) {
                                        Log.info("a: " + a);   
                                    }           
                                }
                            }
                             
                        

内存类规则


1. 资源对象没有关闭。请确保输入输出流创建的对象在使用完成后进行了妥善的关闭处理。

级别:风险

描述:资源对象没有关闭。请确保输入输出流创建的对象在使用完成后进行了妥善的关闭处理。例如java.io.InputStream,java.io.OutputStream,java.io.Reader,java.io.Writer,java.util.zip.ZipFile,java.net.socket等类创建出的对象。

代码示例:

                                                   
                            InputStream in = null;      
                            InputStream in2 = null; 
                            try {
                                in = new URL("http://www.apache.org").openStream(); //触发规则
                                in2 = new URL("http://www.apache.org").openStream();//触发规则
                                
                            } catch (SQLException e) {
                                e.printStackTrace();
                            } 
                             
                        

推荐写法:

                                                   
                            InputStream in = null;      
                            InputStream in2 = null; 
                            try {
                                in = new URL("http://www.apache.org").openStream(); 
                                in2 = new URL("http://www.apache.org").openStream();    
                                
                            } catch (SQLException e) {
                                e.printStackTrace();
                            } finally {
                                IOUtils.closeQuietly(in);//工具类关闭
                                if(in2!=null){
                                    in2.close();//手动关闭
                                }  
                            }
                             
                        
2. 数据库操作相关的资源对象没有关闭。

级别:风险

描述:数据库操作相关的资源对象没有关闭。例如java.sql.Connection,java.sql.Statement,java.sql.ResultSet,android.database.sqlite.SQLiteDatabase,android.database.Cursor等类创建出的对象。

代码示例:

                                                   
                            Connection in3=null; 
                            Statement in4=null; 
                            ResultSet in5=null;
                            try { 
                                in3=DriverManager.getConnection("","","");//触发规则 
                                in4=in3.createStatement();//触发规则
                                in5 = in4.executeQuery("SELECT a, b FROM TABLE2");//触发规则
                            } catch (SQLException e) {
                                // TODO 自动生成的 catch 块
                                e.printStackTrace();
                            } 
                             
                        

推荐写法:

                                                   
                            Connection in3=null; 
                            Statement in4=null; 
                            ResultSet in5=null;
                            try { 
                                in3=DriverManager.getConnection("","","");
                                in4=in3.createStatement();
                                in5 = in4.executeQuery("SELECT a, b FROM TABLE2");
                            } catch (SQLException e) {
                                // TODO 自动生成的 catch 块
                                e.printStackTrace();
                            } finally {
                                DbUtils.closeQuietly(in3);
                                DbUtils.closeQuietly(in4);
                                in5.close();//需要关闭,且需要在finally中关闭
                            }
                             
                        
3. 资源对象在被关闭或者Return之前可能出现异常,导致无法正常关闭或Return。比如连续关闭多个资源对象时没有进行异常捕获,或者资源对象在Return之前进行了未捕获异常的操作。

级别:风险

描述:资源对象在被关闭或者Return之前可能出现异常,导致无法正常关闭或Return。比如连续关闭多个资源对象时没有进行异常捕获,或者资源对象在Return之前进行了未捕获异常的操作。

代码示例:

                                                   
                            FileInputStream fis = null;
                            FileOutputStream fos = null;
                            try {
                              fis = new FileInputStream(new File("e:/a.txt"));
                              fos = new FileOutputStream(new File("e:/a.txt"));//触发规则
                              fos.write(fis.read());
                            } finally {
                              if (fis!=null)  fis.close();
                              if (fos!=null) fos.close();//fos对象在被关闭之前,可以由于fis对象的关闭异常导致fos.close()无法正常执行
                            }
                             
                        

推荐写法:

                                                   
                            FileInputStream fis = null;
                            FileOutputStream fos = null;
                            try {
                              fis = new FileInputStream(new File("e:/a.txt"));
                              fos = new FileOutputStream(new File("e:/a.txt"));
                              fos.write(fis.read());
                            } finally {
                              if (fis!=null){
                                  try {
                                      fis.close();
                                } catch (Exception e) {
                                    // TODO: handle exception
                                }
                              }  
                              if (fos!=null) fos.close();
                            }
                             
                        

基础类规则


2. 有些for循环可以简化为 while循环-这样可以更加简明。

级别:优化

描述:有些for循环可以简化为 while循环-这样可以更加简明。

代码示例:

                                                   
                            public class Foo {
                                void bar() {
                                    for (;true;) true; //触发规则
                                }
                            }
                             
                        
5. 避免从 finally 块中返回 - 这会导致异常捕获后又被抛弃。

级别:建议

描述:避免从 finally 块中返回 - 这会导致异常捕获后又被抛弃。

代码示例:

                                                   
                            public class Bar {
                                public String foo() {
                                    try {
                                        throw new Exception( "My Exception" );
                                    } catch (Exception e) {
                                        throw e;
                                    } finally {
                                        return "A. O. K."; //触发规则
                                    }
                                }
                            }
                             
                        
11. 放错位置的空检查。

级别:风险

描述:这里的空检查是放错位置的。如果变量为空你将得到一个空指针异常。可能因为检查是无用的或者是不正确的。如:if (!string.equals("") && string!=null){}。

代码示例:

                                                   
                            public class Foo {
                                void bar() {
                                    if (a.equals(baz) && a != null) {}
                                    }
                            }
                             
                        
13. 如果自身抛出空指针异常空检查就会遭到破坏,比如你使用 ||代替 &&,反之亦然,如(应是&&):if (string!=null || !string.equals("")){}。

级别:风险

描述:如果自身抛出空指针异常空检查就会遭到破坏,比如你使用 ||代替 &&,反之亦然,如(应是&&):if (string!=null || !string.equals("")){}。

代码示例:

                                                   
                            public String bar(String string) {
                              // should be &&
                                if (string!=null || !string.equals(""))
                                    return string;
                              // should be ||
                                if (string==null && string.equals(""))
                                    return string;
                            }
                             
                        
16. 避免使用 IP硬编码。

级别:建议

描述:一个应用中的硬编码 IP将使系统在某些情况下无法发布(例如内网IP暴露)。

代码示例:

                                                   
                            public class Foo {
                                private String ip = "127.0.0.1";    // not recommended
                            }
                             
                        
29. 避免对字符串对象调用toString()方法

级别:优化

描述:避免对字符串对象调用toString()方法

代码示例:

                                                   
                            private String baz() {
                                String bar = "howdy";
                                return bar.toString();
                            }
                             
                        
30. 避免在StringBuffer的构造器或append()方法中连接非常量类型。

级别:优化

描述:避免在StringBuffer的构造器或append()方法中连接非常量类型。

代码示例:

                                                   
                            // Avoid this, two buffers are actually being created here
                            StringBuffer sb = new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir"));
                                
                                // do this instead
                            StringBuffer sb = new StringBuffer("tmp = ");
                            sb.append(System.getProperty("java.io.tmpdir"));
                             
                        
31. 使用equalsIgnoreCase()比将字符串大小写转换一致后再比较要快。

级别:优化

描述:使用equalsIgnoreCase()比将字符串大小写转换一致后再比较要快。

代码示例:

                                                   
                            boolean answer1 = buz.toUpperCase().equals("baz");          // should be buz.equalsIgnoreCase("baz")
    
                            boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz");     // another unnecessary toUpperCase()
                             
                        
36. 低效的空字符串检查。

级别:优化

描述:用String.trim().length()来判断字符串是否空是低效的做法,因为它会创建一个新的字符串对象然后判断大小。考虑创建一个静态的方法循环String,用isWhitespace()检查每个字符如果遇到非空白字符就返回false。

代码示例:

                                                   
                            public void bar(String string) {
                                if (string != null && string.trim().size() > 0) {
                                    doSomething();
                                }
                            }
                             
                        
40. StringBuffer使用字符初始化

级别:优化

描述:使用‘==’或‘!=’比较字符串大小只是比较两边的常量池的引用。

代码示例:

                                                   
                            public boolean test(String s) {
                                if (s == "one") return true;        // unreliable
                                if ("two".equals(s)) return true;   // better
                                return false;
                            }
                             
                        
48. 空的catch块

级别:优化

描述:发现空的 catch 块没做任何异常处理的事,在大多数情形下,这会吞噬一些应该被处理或报告的异常。

代码示例:

                                                   
                            public void doSomething() {
                              try {
                                FileInputStream fis = new FileInputStream("/tmp/bugger");
                              } catch (IOException ioe) {
                                  // not good
                              }
                            }
                             
                        
49. 空的if表达式

级别:优化

描述:发现使用 if 进行了条件判断,但是判断之后没做任何处理。

代码示例:

                                                   
                            public class Foo {
                             void bar(int x) {
                              if (x == 0) {
                               // empty!
                              }
                             }
                            }
                             
                        
50. 空的while表达式

级别:优化

描述:发现空的while表达式,如果是一个定时的循环,你应该在循环体内使用 Thread.sleep();如果是对于退出处理做的一个处理大量事情的while循环,重写代码使它更清晰。

代码示例:

                                                   
                            void bar(int a, int b) {
                                while (a == b) {
                                // empty!
                                }
                            }
                             
                        
51. 空的try块

级别:优化

描述:避免空的try块。

代码示例:

                                                   
                            public class Foo {
                             public void bar() {
                              try {
                              } catch (Exception e) {
                                e.printStackTrace();
                              }
                             }
                            }
                             
                        
52. 空的finally块

级别:优化

描述:避免空的 finally 块 - 这些是可以删掉的。

代码示例:

                                                   
                            public class Foo {
                             public void bar() {
                              try {
                                int x=2;
                               } finally {
                                // empty!
                               }
                             }
                            }
                             
                        
53. 空的switch表达式

级别:优化

描述:避免空的 switch表达式。

代码示例:

                                                   
                            public void bar() {
                                int x = 2;
                                switch (x) {
                                // once there was code here
                                // but it's been commented out or something
                                }
                            }
                             
                        
54. 空的Synchronized块

级别:优化

描述:避免空的 synchronized 块 - 它们是无用的。

代码示例:

                                                   
                            public class Foo {
                             public void bar() {
                              synchronized (this) {
                               // empty!
                              }
                             }
                            }