代码之旅

I love Coding !

位运算实现组合选项

在实际开发中常会用到选项,选项开启和关闭可以有效的控制代码执行逻辑。

对于选项,我们可以简单的用类的一个属性去判断。也可以使用一些编程技巧,通过一个数字来表示组合选项。

一个简单的例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class ByteOption {

public enum Option {
/*
option
*/
OPTION_1(op1),
OPTION_2(op2),
OPTION_3(op3),
OPTION_4(op4),
OPTION_5(op5),
OPTION_6(op6),
OPTION_7(op7)
;

byte value;

Option(byte i) {
value = i;
}
}
// 将多个属性设置为不冲突的二进制数
public static byte op1 =0b00000001;
public static byte op2 =0b00000010;
public static byte op3 =0b00000100;
public static byte op4 =0b00001000;
public static byte op5 =0b00010000;
public static byte op6 =0b00100000;
public static byte op7 =0b01000000;
private static int ALL = 0b11111111;


private byte op = 0b00000000;

public void enableOption(Option option){
op = (byte) (op | option.value);
}

public void disableOption(Option option){
op = (byte) (op & (option.value^ALL));
}

public boolean isEnable(Option option){
return option.value == (op & option.value);
}
}

Java位移操作符

运算符<<(左移),>>(右移)和 >>>(无符号右移)称为移位运算符。移位运算符的左侧操作数是要移位的值; 右侧操作数指定移位距离。下面是语法描述:

1
2
3
4
5
ShiftExpression:
AdditiveExpression
ShiftExpression << AdditiveExpression
ShiftExpression >> AdditiveExpression
ShiftExpression >>> AdditiveExpression
  • n << s的意思是n左移s个bit位,这相当于 n2sn*2^s,注意溢出。
  • n >> s的意思是n带符号位右移s个bit位,若左操作数是正数,则高位补“0”,若左操作数是负数,则高位补“1”,这相当于 n/2sn/2^s
  • n >>>s的意思是不带符号右移,无论左操作数是正数还是负数,在高位都补“0”。
    • 如果n是正数,那么结果等同于n >> s
    • 如果n是负数,且类型是int,那么结果等同于(n >> s) + (2 << ~s)
    • 如果n是负数,且类型是long,那么结果等同(n >> s) + (2L << ~s)

按位补码运算符: ~

shift表达式的类型是左侧操作数的提升类型。

  • 如果左手操作数的提升类型是int,则只使用右手操作数的五个最低位作为移位距离.
  • 如果左侧操作数的提升类型是long,则只使用右侧操作数的六个最低位作为移位距离.
1
2
3
5 >> 32 == 5
// 5 >> 0
// 32 100000 后5位是 00000

参考

JVM 字节码指令

Java源码在运行之前都要编译成为字节码格式(如.class文件),然后由ClassLoader将字节码载入运行。在字节码文件中,指令代码只是其中的一部分,里面还记录了字节码文件的编译版本、常量池、访问权限、所有成员变量和成员方法等信息(详见Java字节码规范)。本文主要简单介绍不同Java指令的功能。

阅读全文 »

JVM 查看本机代码

JVM支持使用PrintAssembly选项来检查JIT编译器生成的代码。对了解代码是如何执行的,以及JIT编译器如何工作和优化代码有很大帮助。

阅读全文 »

Java 动态代理机制

Java 动态代理

本篇文章引用源码默认为Java 8

阅读全文 »

设计模式之控制反转

控制反转(Inversion of Control)是一种是面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度。其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。

在传统编程中,业务逻辑的流由静态绑定的对象确定。通过反转控制,流取决于在程序执行期间构建的对象图。这种动态流是通过抽象定义的对象交互实现的。此运行时绑定是通过依赖项注入或服务定位器等机制实现的。在 IoC 中,代码也可以在编译期间静态链接,但通过从外部配置读取其描述而不是在代码本身中直接引用来查找要执行的代码。

我们来看下,为什么说控制反转(IOC)是一种解耦:

  • 在没有引入IOC容器之前,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
  • 软件系统在引入IOC容器之后,这种情形就完全改变了,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。

通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

控制反转和依赖注入的区别: IoC框架使用依赖注入作为实现控制反转的方式,但是控制反转还有其他的实现方式,所以不能将控制反转和依赖注入等同。

阅读全文 »

Java 依赖注入规范:javax-inject

JSR-330 是Java的依赖注入规范。标准的依赖注入的类在javax.inject中定义。

阅读全文 »

设计模式之访问者模式

访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为“对象结构”,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。

阅读全文 »

设计模式之依赖注入

依赖关系注入是一种软件设计模式,其中一个或多个依赖关系(或服务)被注入或通过引用传递到依赖对象(或客户端)中,并成为客户端状态的一部分。该模式将客户端依赖项的创建与其自身行为分开,这允许程序设计松散耦合并遵循控制反转和单一责任原则。

简单来说,依赖注入通过请求获取它们的子组件而不是通过创建它们来获取, 将依赖关系的创建与其自身行为分开。

阅读全文 »

单例模式

单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。

阅读全文 »