java中位运算传参_java基础之位运算讲解于实战

一、基础知识点概括

在查看源码中,经常会看到很多这样的符号“&”、“|”、“~”,"^","<>"很多人对此比较头疼,现在来简单讲述下这些符号的用法以及在项目中的实用:

1、与运算符 &

知识点:两位同时为“1”,结果才为“1”,否则为“0”。

运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;

其实就是运算的位要完全一样,才保持原样,否则就变为0。

2、或运算符 |

知识点:只要有一位为1,其值为1,否则为“0”。

运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1;

其实就是只要有1,结果就为1。

3、与运算符 ^

知识点:只要有两个是相异的,为1,否则为“0”。

运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=0;

其实就是不同为1,相同为0。

4、与运算符 ~

知识点:对各二进位按位求反。

~(000001)=111110

5、左移运算符 <<

知识点:左移运算符“<

例如: a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移 4位后为00110000(十进制48)。

6、又移运算符 >>

知识点:右移运算符“>>”是双目运算符。右移n位就是除以2的n次方。

例如:设 a=15,a>>2 表示把000001111右移为00000011(十进制3)。

二、运算符在源码中的体现

首先是左移动和右移运算符,想到了啥?

android 源码里经典的MeasureSpec类啊。我们来看下其成员变量:

public static class MeasureSpec {

private static final int MODE_SHIFT = 30;

private static final int MODE_MASK = 0x3 << MODE_SHIFT;

/** @hide */

@IntDef({UNSPECIFIED, EXACTLY, AT_MOST})

@Retention(RetentionPolicy.SOURCE)

public @interface MeasureSpecMode {}

/**

* Measure specification mode: The parent has not imposed any constraint

* on the child. It can be whatever size it wants.

*/

public static final int UNSPECIFIED = 0 << MODE_SHIFT;

/**

* Measure specification mode: The parent has determined an exact size

* for the child. The child is going to be given those bounds regardless

* of how big it wants to be.

*/

public static final int EXACTLY = 1 << MODE_SHIFT;

/**

* Measure specification mode: The child can be as large as it wants up

* to the specified size.

*/

public static final int AT_MOST = 2 << MODE_SHIFT;

首先我们都知道measure的参数就是传measurespec的两个值进去,也就是两个32位的int值,而这个一个32位的int值包括了宽高信息以及测量模式,那实现原理就是如此。

从源码中看到MODE_MASK其实就是

0000 0000 0000 0000 0000 0000 0000 0011

左移30位就是

1100 0000 0000 0000 0000 0000 0000 0000

以此类推:

UNSPECIFIED:

0000 0000 0000 0000 0000 0000 0000 0000

EXACTLY:

0100 0000 0000 0000 0000 0000 0000 0000

AT_MOST:

1000 0000 0000 0000 0000 0000 0000 0000

由此可见:

把32位的前2位是测量模式,后30位是值的存放地,再来看下makeMeasureSpec的具体实现:

public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,

@MeasureSpecMode int mode) {

if (sUseBrokenMakeMeasureSpec) {

return size + mode;

} else {

return (size & ~MODE_MASK) | (mode & MODE_MASK);

}

}

分析下:

比如size是503:(传进去size),mode是EXACTLY

size & ~MODE_MASK

~MODE_MASK 就是

0011 1111 1111 1111 1111 1111 1111 1111

503的二进制是:

0000 0000 0000 0000 0000 0001 1111 0111

结果为:

0000 0000 0000 0000 0000 0001 1111 0111

(mode & MODE_MASK);

mode 为

0100 0000 0000 0000 0000 0000 0000 0000

MODE_MASK:

1100 0000 0000 0000 0000 0000 0000 0000

结果就是

0100 0000 0000 0000 0000 0000 0000 0000

两者的结果为

0100 0000 0000 0000 0000 0001 1111 0111

此时宽高信息以及测量模式都保存在了一个int值中

然后在看下get的代码:

@MeasureSpecMode

public static int getMode(int measureSpec) {

//noinspection ResourceType

return (measureSpec & MODE_MASK);

}

/**

* Extracts the size from the supplied measure specification.

*

* @param measureSpec the measure specification to extract the size from

* @return the size in pixels defined in the supplied measure specification

*/

public static int getSize(int measureSpec) {

return (measureSpec & ~MODE_MASK);

}

很明显把刚刚的值通过&运算符与遮罩mode(mode_mask)运算后就能获得宽高信息以及尺寸的大小了。

总结;

只介绍了部分的运算符的一处用法,其实在view里的mViewFlags也是相同的用法,省去了很多变量的命名。

最后很多用法等着我们去挖掘~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值