zoukankan      html  css  js  c++  java
  • 编程技巧:使用整数同时进行多个true|false判断

    情景 :

    假设需要判断某银行用户的其中一个账号(profileA),币种(Currency)为人民币(CNY),余额是否大于1,0000,然后进行某业务逻辑处理。

    概述:

    为了进行这种判断,需要判断/验证该账号是否为profileA、币种是否为CNY,余额是否大于1,0000这3种情况,在代码中可能会写出一大堆if...else语句,不仅不雅观,还不便于理解。如果使用一个整数int来同时标识多个判断的结果,就可以避免一大堆if...else的情况。当然这个例子只是作为demo说明情况,具体怎么处理还得根据实际出发,而且要是需要作更多判断,这个方法就会更实用。


    分析说明:

    对于计算机来说,所有数据都是由二进制数来表示,对于每一位(bit)来说,有0或1这2种情况,分别对应的boolean值为false和true。在Java中,每个int的大小为4 byte(注意是基本类型的int,而不是引用类型的Integer),一共有4*8=32位(bit),每一个位可对应一个boolean值的话,那么1个int最多可以同时对应32个boolean值。

    以JDK中的实现,java.lang.reflect.Modifier为例:

    1. 定义每个二进制位数上的含义(modifier),并得到相应十六进制数;(其实十进制也可以,只是在十六进制下其实就是1/2/4/8这几个数字在不同的位上循环,比十进制数要直观,可以在下图感受一下)
    2. 如果同时验证多个条件,可以通过逻辑与(OR, "|")将多个条件组合起来。例如可以自定义“同时满足public、static、final这3个修饰词”这个条件:
      • public static final int PUBLIC_STATIC_FINAL = PUBLIC | STATIC | FINAL;
    3. 将要验证的编码(整数)传入,与modifier进行逻辑与(AND, "&")运算,所得结果再与modifier比较即可;
      • return (mod & modifier) == modifier;

     1 public class Modifier{
     2     public static final int PUBLIC = 0x00000001;    //0001
     3     public static final int PRIVATE = 0x00000002;    //0010
     4     public static final int PROTECTED = 0x00000004;    //0100
     5     public static final int STATIC = 0x00000008;    //1000
     6     ......
     7     public static boolean isPublic(int mod) {
     8         return (mod & PUBLIC) != 0;
     9     }
    10     ......
    11 }
    展开/收起

    验证:主要看System.out.println();打印输出的几行即可,其他都是辅助理解。

     1 package com.scv.lawrence;
     2 import java.lang.reflect.Field;
     3 import java.lang.reflect.Modifier;
     4 
     5 public class Demo {
     6     public static final int STATIC_FINAL = Modifier.STATIC | Modifier.FINAL;
     7     public static final int PUBLIC_STATIC_FINAL = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
     8     
     9     public static boolean compare(int mod, int token){
    10         return (mod & token) == token;
    11     }
    12     
    13     private static int age = 999;
    14     private static final String name = "Lawrence";
    15     public final String gender = "Male";
    16     
    17     public static final int PUBLIC_STATIC = Modifier.PUBLIC | Modifier.STATIC;
    18 
    19     public static void main(String[] args) throws Exception {
    20         Field myAge = Demo.class.getDeclaredField("age");
    21         Field myName = Demo.class.getDeclaredField("name");
    22         Field myGender = Demo.class.getDeclaredField("gender");
    23         
    24         int ageMod = myAge.getModifiers();
    25         int nameMod = myName.getModifiers();
    26         int genderMod = myGender.getModifiers();
    27         
    28         System.out.println("age的modifier(十进制): " + ageMod);
    29         System.out.println("	" + "是否包含static和final:" + compare(ageMod, STATIC_FINAL));
    30         System.out.println("	" + "是否包含static:" + compare(ageMod, Modifier.STATIC));
    31         
    32         System.out.println("************");
    33         System.out.println("name的modifier(十进制): " + nameMod);
    34         System.out.println("	" + "是否包含static和final:" + compare(nameMod, STATIC_FINAL));
    35         System.out.println("	" + "是否包含static:" + compare(nameMod, Modifier.STATIC));
    36         
    37         System.out.println("************");
    38         System.out.println("gender的modifier(十进制): " + genderMod);
    39         System.out.println("	" + "是否包含static和final:" + compare(genderMod, STATIC_FINAL));
    40         System.out.println("	" + "是否包含static:" + compare(genderMod, Modifier.STATIC));
    41     }
    42         
    43 }
    44 
    45 /* output:
    46  * 
    47  * age的modifier(十进制): 10
    48  * 是否包含static和final:false
    49  * 是否包含static:true
    50  * ************
    51  * name的modifier(十进制): 26
    52  * 是否包含static和final:true
    53  * 是否包含static:true
    54  * ************
    55  * gender的modifier(十进制): 17
    56  * 是否包含static和final:false
    57  * 是否包含static:false
    58  */
    展开/收起

    场景应用:

    1.  自定义Profile类,在实例化的时候就计算并保存其类型;
    2. 在ToolBox类中定义各种标识的含义;
    3. 在main()中对profile进行验证并执行相应业务逻辑;
     1 package com.scv.lawrence;
     2 
     3 public class Fragment {
     4 
     5     public static void main(String[] args) {
     6         Profile[] profiles = {new Profile("ABC0001", "CNY", 12_0000),
     7                         new Profile("SRC0001", "CNY", 21_0000),    //target profile
     8                         new Profile("ZZZ666GRE", "USD", 9000)};
     9         
    10         for(Profile p: profiles){
    11             if(ToolBox.isTargetProfile(p, ToolBox.PRO_A_CNY_GT)){
    12                 //Do something.
    13                 System.out.println("Got target profile.");
    14             };
    15         }
    16         
    17     }
    18     
    19 }
    20 
    21 class ToolBox{
    22     public static final int PROFILE_A = 0x0000_0001;    //0001
    23     public static final int CNY = 0x0000_0002;    //0010
    24     public static final int GT_10K = 0x0000_0004;    //0100
    25     public static final int LT_10K = 0x0000_0008;    //1000
    26     
    27     public static final int PRO_A_CNY_GT = PROFILE_A | CNY | GT_10K;    //0111,profileA、币种为人民币、余额大于1,0000
    28     public static final int PRO_A_CNY_LT = PROFILE_A | CNY | LT_10K;    //1111,profileA、币种为人民币、余额不足1,0000
    29     
    30     protected static void setToken(Profile p){
    31         if("SRC0001".equals(p.getName())) p.token += 0x00000001;
    32         if("CNY".equals(p.getCurrency())) p.token += 0x00000002;
    33         if(p.getBalance() > 1_0000) p.token += 0x00000004;
    34     }
    35     
    36     public static boolean isTargetProfile(Profile p, int mod){
    37         return (p.getToken() & mod) == mod;
    38     }
    39 }
    40 
    41 class Profile{
    42     private String name;
    43     private String currency;
    44     private double balance;
    45     protected int token;
    46     
    47     public int getToken(){
    48         return this.token;
    49     }
    50     
    51     public Profile() {}
    52     public Profile(String name, String currency, double balance){
    53         this.name = name;
    54         this.currency = currency;
    55         this.balance = balance;
    56         ToolBox.setToken(this);
    57     }
    58     public String getName() {
    59         return name;
    60     }
    61     public void setName(String name) {
    62         this.name = name;
    63     }
    64     public String getCurrency() {
    65         return currency;
    66     }
    67     public void setCurrency(String currency) {
    68         this.currency = currency;
    69     }
    70     public double getBalance() {
    71         return balance;
    72     }
    73     public void setBalance(double balance) {
    74         this.balance = balance;
    75     };
    76     
    77     
    78 }
    View Code

    如要添加新的业务,只需要在ToolBox定义新的内容,即可。

    p.s:数字下划线是JDK 1.7的语法糖,仅有方便阅读(人类)的作用,编译时会自动去掉。如1_0000_0000、100_000_000、100000000这几个数字在编译后都一样,但极大地方便了阅读。


    优点:

    • 代码量少,避免大量if...else判断,易于维护;
    • 高效;

    缺点:

    • 初次接触的话可能不易理解;

     与switch相比:

    • 轻松进行多个条件的判断,且可以进行子集条件的判断,即对于满足A|B|C|D的条件,也会同时满足A|B、B|D或B|C|D等等。switch并不具备这样的能力。

    如有纰漏,还望指正。

  • 相关阅读:
    06 继承与多态
    动手动脑 4 String 类
    字串加密
    课后作业(查询类对象创建个数)
    动手动脑 3 类与对象
    动手动脑 (第二次)
    IOS 网络判断
    ios常用的几个动画代码
    iOS Get方式带中文不能请求网络
    UILabel Text 加下划线
  • 原文地址:https://www.cnblogs.com/lawrencechen/p/4889701.html
Copyright © 2011-2022 走看看