2进制

计算机的底层全部都是2进制的!

byte short int long float double char String

Java 利用算法支持了10进制:

  • parseInt 将10进制转换为2进制
  • toString 将2进制转换为10进制

原理:


java中二进制的时间戳 java二进制显示_进制


java中二进制的时间戳 java二进制显示_进制_02

案例:

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


java中二进制的时间戳 java二进制显示_进制_03

案例:

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进制数的一半作为负数的算法, 称为补码


java中二进制的时间戳 java二进制显示_进制_04

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

编码:


java中二进制的时间戳 java二进制显示_java中二进制的时间戳_05

解码:


java中二进制的时间戳 java二进制显示_进制_06

代码:

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(类名);


java中二进制的时间戳 java二进制显示_java中二进制的时间戳_07

动态创建对象

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 的快捷菜单用到了哪些技术?
答: 反射 呗!