2进制
计算机的底层全部都是2进制的!
byte short int long float double char String
Java 利用算法支持了10进制:
- parseInt 将10进制转换为2进制
- toString 将2进制转换为10进制
原理:
案例:
public class Demo01 {
public static void main(String[] args) {
/*
* 显示整数的2进制, 也就是显示内存中实际的2进制
* 存储情况.
*/
//编译以后 "50" 就被编译为2进制
int i = 50;
System.out.println(
Integer.toBinaryString(i));
//Java输出整数时候自动调用了Integer.toString()
//将2进制转换为10进制字符串输出!
System.out.println(i); //50
}
}
案例:
public class Demo02 {
public static void main(String[] args) {
/*
* 输出0~50全部的2进制
*/
for (int i = 0; i <= 50; i++) {
System.out.println(
StringUtils.leftPad(
Integer.toBinaryString(i), 32, "0"));
}
}
}
16进制
16进制用于简写2进制!!!
2进制书写繁琐! 使用16进制可以将2进制每4位数缩写为一个16进制数字
01101001 00100001 11101001 00101001
简写为
69ade929
案例:
public class Demo03 {
public static void main(String[] args) {
/*
* 16进制用于缩写2进制.
* 16进制就是2进制!!!
*/
int i = 0x69ade929;
System.out.println(
Integer.toBinaryString(i));
//Java 利用算法 parseInt(hex, 16) 将16进制
//转换为2进制.
String hex = "69ade929";
int n = Integer.parseInt(hex, 16);
System.out.println(
Integer.toBinaryString(n));
}
}
补码
将2进制数的一半作为负数的算法, 称为补码
max = 01111111 11111111 11111111 11111111
int max = 0x7fffffff;
案例:
public class Demo05 {
public static void main(String[] args) {
/*
* 输出-50 到 50的全部补码
*/
for(int i=-50; i<=50; i++){
System.out.println(
StringUtils.leftPad(
Integer.toBinaryString(i),32,"0"));
}
}
}
案例:负数
public class Demo04 {
public static void main(String[] args) {
int i = -3;
System.out.println(
Integer.toBinaryString(i));
System.out.println(i);//-3
long l = -3L;
System.out.println(
Long.toBinaryString(l));
}
}
案例:
public class Demo06 {
public static void main(String[] args) {
/*
* 输出整数的最大值
*/
//int max = 0x7fffffff;
int max = Integer.MAX_VALUE;
System.out.println(max);
System.out.println(
Integer.toBinaryString(max));
/*
* 输出整数的最小值
*/
int min = 0x80000000;
System.out.println(min);
System.out.println(
Integer.toBinaryString(min));
}
}
题目
int i = 0xffffffff;
System.out.println(i);
如上代码输出结果:
A.2147483647 B.-2147483647 C.2147483648 D.-2147483648 E.-1
补码互补对称现象
面试题:
System.out.println(~3+1);
如上代码的结果是: ( C )
A.3 B.4 C.-3 D.-4
原理如下:
3 = 00000000 00000000 00000000 00000011 = 3
~3 = 11111111 11111111 11111111 11111100 = -4
~3+1 = 11111111 11111111 11111111 11111101 = -3
System.out.println(~20+1);
如上代码的结果是: ( C )
A.20 B.21 C.-20 D.-21
原理:
20 = 00000000 00000000 00000000 00010100 = 20
~20 = 11111111 11111111 11111111 11101011 = -21
~20+1 = 11111111 11111111 11111111 11101100 = -20
System.out.println(~20);
如上代码的结果是: ( D )
A.20 B.21 C.-20 D.-21
System.out.println(~-20);
如上代码的结果是: ( E )
A.20 B.21 C.-20 D.-21 E.19
2进制计算
~ 取反运算
& 与运算
| 或运算
>>> 逻辑右移位运算
>> 数学右移位运算
<< 左移位运算
& 与运算(逻辑乘法)
规则:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
| 或运算 (逻辑加法)
规则:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
>>> 逻辑右移位运算
每个位向右移位, 高位补0
例子:
n = 00101011 10110111 10100101 11011010
m=n>>>1 = 000101011 10110111 10100101 1101101
k=n>>>2 = 0000101011 10110111 10100101 110110
<< 左移位运算
每个位向左移位, 低位补0
例子:
n = 00101011 10110111 10100101 11011010
m=n<<1 = 0101011 10110111 10100101 110110100
k=n<< 2 = 101011 10110111 10100101 1101101000
案例: 利用2进制计算, 将 '中' 进行UTF-8编码
int c = '中';//0x4e2d
// c 00000000 00000000 0100 1110 0010 1101
//utf-8 b1= 1110XXXX
//utf-8 b2= 10XXXXXX
//utf-8 b3= 10XXXXXX
编码:
解码:
代码:
public class Demo07 {
public static void main(String[] args)
throws Exception{
/*
* 利用2进制计算实现 中文字的UTF-8编码
*/
int c = '中';
//UTF-8 空白编码格式:
int b1=0xe0;
int b2=0x80;
int b3=0x80;
//填充第一个编码
int c1 = (c>>>12) | b1;
//填充第二个编码
int c2 = (c>>>6) & 0x3f | b2;
//填充第三个编码
int c3 = c & 0x3f | b3;
print(c);
print(b1);
print(c>>>12);
print(c1);
print(c2);
print(c3);
//解码: 测试
String str = new String(
new byte[]{(byte)c1,(byte)c2,(byte)c3}
, "UTF-8");
System.out.println(str);
//utf-8 解码的工作原理
int ch = (c1<<12)& 0xffff |
(c2<<6) & 0xfff |
c3 & 0x3f;
System.out.println((char)ch);//中
}
public static void print(int c) {
System.out.println(
StringUtils.leftPad(
Integer.toBinaryString(c),32,"0"));
}
}
经典面试题目:
优化计算 n % 4 可以优化为 ( n & 0x3 )
n = 5 = 00000000 00000000 00000000 00000101 % 4 = 1
n = 6 = 00000000 00000000 00000000 00000110 % 4 = 2
n = 7 = 00000000 00000000 00000000 00000111 % 4 = 3
n = 8 = 00000000 00000000 00000000 00001000 % 4 = 0
n = 9 = 00000000 00000000 00000000 00001001 % 4 = 1
优化计算 n % 8 可以优化为 ( n & 0x7 )
优化计算 n % 16 可以优化为 ( n & 0xf )
if (year & 0x3 == 0){
//可以被4整除!
}
移位计算的数学意义
142323.
1423230. 扩大10倍
14232300. 扩大10倍
142323.
1423230. 扩大10倍
14232300. 扩大10倍
小数点不动, 数字向左移动
i = 00000000 00000000 00000000 00110010. = 50
i<<1 = 0000000 00000000 00000000 001100100. = 100
i<<2 = 000000 00000000 00000000 0011001000. = 200
案例:
public class Demo08 {
public static void main(String[] args) {
/*
* 左移位的数学意义
*/
int n = 50;
int m = n<<1;
int k = n<<2;
System.out.println(m);
System.out.println(k);
Demo07.print(n);
Demo07.print(m);
Demo07.print(k);
/*
* 右移位的数学意义
*/
n = 50;
m = n>>1; //>>>
k = n>>2; //>>>
System.out.println(m);//25
System.out.println(k);//12
Demo07.print(n);
Demo07.print(m);
Demo07.print(k);
/*
* >>> >> 在正数情况下一样
* >>> >> 在负数情况下不同
* >> 负时候, 高位补1
* >>> 负时候, 高位补0
*
* n = 11111111 11111111 11111111 11001110 -50
* n>>1 111111111 11111111 11111111 1100111 -25
* n>>2 1111111111 11111111 11111111 110011 -13
* n>>>1 011111111 11111111 11111111 1100111
*
* 将 >> 称为数学移位计算(向小方向取整)
* 将 >>> 称为逻辑移位计算
*
*/
n = -50;
n = n>>1;
k = n>>>1;
System.out.println(n);
System.out.println(k);
}
}
反射
反射是Java提供的API, 是Java 中的动态执行机制, 可以动态加载类,动态创建对象,动态访问属性,动态调用方法. 等
甚至打破访问限制, 访问私有成员(打破了封装)
静态执行
按照编译期间约定执行执行顺序, 在运行期间顺序执行.
Foo foo = new Foo();
foo.test();
动态执行
编译期间不指定执行顺序, 在运行期间才缺点创建那个对象, 执行方法.
利用反射API, 可以实现动态执行!
动态加载类
Class cls = Class.forName(类名);
动态创建对象
Object obj = cls.newInstance();
这个类型必须有无参数构造器, 如果没有将抛出异常, 反射提供了调用有参数构造器的API方法! 不是重点!
反射API可以动态获取类的信息
包括: 类中声明的属性, 类中声明的方法, 等
案例:
public class Foo {
private int id = 5;
public String name = "Tom";
public void test(){
System.out.println("test()");
}
public void hello(){
System.out.println("Hello()");
}
}
public class Demo01 {
public static void main(String[] args)
throws Exception{
/*
* 利用反射API动态加载类到方法区
* 在运行期间加载一个类到内存中
*/
Scanner in = new Scanner(System.in);
System.out.print("输入类名:");
//在运行期间得到类名
String className = in.nextLine();
//动态加载类, 如果类名错误将抛出异常
Class cls = Class.forName(className);
//显示加载的结果
System.out.println(cls);
//动态创建对象
Object obj = cls.newInstance();
System.out.println(obj);
//Declared: 声明的 Field: 字段,属性
//动态获取类中声明的全部属性信息
Field[] fields=cls.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//动态获取类中声明的全部方法信息
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
}
}
经典题目:
Eclipse 的快捷菜单用到了哪些技术?
答: 反射 呗!