Java学习笔记-《Java程序员面试宝典》-第四章基础知识-4.4基本类型与运算(4.4.5-4.4.10)

来源:互联网 发布:中科院下属企业知乎 编辑:程序博客网 时间:2024/05/17 22:30

4.4.5强制类型转换的注意事项有哪些

Java语言在涉及byte、short和char类型的运算时,首先会把这些类型的变量值强制转换为int类型,然后对int类型的值进行计算,最后得到的结果也是int类型。因此,如果把这两个short类型的值相加,最后得到的结果是int类型;如果把两个byte类型相加,最后得到的也是一个int类型的值。如果需要得到short类型的结果,就必须显示的把运算结果转换为short类型。
例如对于语句:short s1 = 1;s1 = s1 +1,由于在进行加法运算时,等号右边的s1会先被转换为int类型,因此s1+1的结果是int类型,可是等号左边的s1是short类型,编译器会报错,需要强制转换。所以正确的写法是:short s1=1;s1=(short)(s1+1)。
有一种例外情况,“+=”为Java语言规定的运算法,Java编译器会对其进行特殊处理,因此short s1=1;s1+=1能够编译通过。

4.4.6运算符的优先级是什么

Java语言中有许多运算符,由于运算符优先级的问题经常会导致程序出现意想不到的结果,运算符优先级如下图:
这里写图片描述
在实际使用过程中如果不确定优先级,最好使用括号运算符来控制运算顺序。
例如在: 5 >>2+10>>2式子中,由于“+”的优先级高于“>>”,所以等价于:5>>(2+10)>>2即5>>12>>2,所以结果为0.

4.4.7Math类中的round、ceil和floor方法的功能各是什么

round、ceil和floor方法位于Math类中,Math是一个包含了许多数学常量与计算方法的类,位于java.lang包下,能自动导入,而且Math类里边的方法全是静态方法。下面重点介绍这三个方法代表的含义。
1>round方法表示四舍五入。round,意为“环绕”,实现原理是在原来的数字基础上先增加0.5然后再向下取整,等同于(int)Math.floor(x+0.5f)。它的返回值类型为int类型,例如,Math.round(1.4)=1,Math.round(-1.4)=-1。
2>ceil方法的功能是向上取整。ceil,意为“天花板”,顾名思义是对操作数取顶,Math.ceil(a),就是取大于a的最小的整数值。需要注意的是,它的返回值类型并不是int型,而是double型。若a是正数,则把小数“入”,若a是负数,则把小数“舍”。例如,Math.ceil(1.4)=2.0,Math.ceil(-1.4)=-1.0
3>floor方法的功能是向下取整。floor,以为“地板”,顾名思义是对操作数取底。Math.floor(a),就是取小于a的最大的整数值,它的返回值类型与ceil方法一样,也是double型。若a是正数,则把小数“舍”;若a是负数,则把小数“入”。例如,Math.floor(1.4)=1.0,Math.floor(-1.4)=-2.0。

4.4.8++i与i++有什么区别

在编程时,经常会遇到变量的自增、自减操作,尤其在循环中用的最多。以自增为例,有两种自增方式:前置和后置,即++i和i++,他们的不同点在于i++是在程序执行完毕后进行自增,而++i是在程序开始执行前进行自增。
示例如下:

public class Test {    public static void main(String[] args){        int i=1;        System.out.println(i+++i++);        System.out.println("i="+i);        System.out.println(i++ + ++i);        System.out.println("i="+i);        System.out.println(i+++i+++i++);        System.out.println("i="+i);    }}运行结果:3i=38i=518i=8

这里只要注意到如果有int a=i++;那么a是i原先的值,而在这句代码执行完毕之后,i就增加了1;如果有int b=++i;那么b就是对i加1之后的值,而在这句代码执行完毕之后,i也增加了1。

看一道面试题:假设x=1,y=2,z=3,则表达式y+=z–/++x的值是多少?
分析:在表达式中z– = 3,++x=2,那么就是3/2=1.5,但是这里是int类型的操作,那么就会对结果只取整数部分所以表达式为y+=1,也就是3。

4.4.9 如何实现无符号数的右移操作

Java提供了两种右移运算符:“>>”和“>>>”。其中,“>>”被称为有符号右移运算,“>>>”被称为无符号右移运算符,他们的功能是将参与运算的对象对应的二进制数右移指定的位数。二者的不同点在于“>>”在执行右移操作时,若参与运算的数字为正数,则在高位补0;若为负数,则在高位补1。而“>>>”则不同,无论参与运算的数字为正数或为负数,在执行运算时,都会在高位补0。
此外,需要特别注意的是。在对char、byte、short类型的数进行位移操作前,和其他的运算操作一样,编译器都会自动的将数值转化为Int类型,然后进行操作。由于int型变量只占4Byte,因此当右移的位数超过32bit时,位移运算没有任何意义。所以,在Java中,为了保证位移位数的有效性,以使右移的位数不超过32bit,采用了取余的操作,即,使a>>n等价于a>>(n%32)
示例如下:

public class TestBitMove {    public static void main(String[] args)    {        int i=-4;        System.out.println("--------int>>:"+i);        System.out.println("位移前二进制:"+Integer.toBinaryString(i));        i >>= 1;        System.out.println("位移后二进制:"+Integer.toBinaryString(i));        System.out.println("--------int>>:"+i);        System.out.println("");        i=-4;        System.out.println("--------int>>>:"+i);        System.out.println("位移前二进制:"+Integer.toBinaryString(i));        i >>>= 1;        System.out.println("位移后二进制:"+Integer.toBinaryString(i));        System.out.println("--------int>>>:"+i);        System.out.println("");        short j=-4;        System.out.println("--------short>>:"+j);        System.out.println("位移前二进制:"+Integer.toBinaryString(j));        j >>= 1;        System.out.println("位移后二进制:"+Integer.toBinaryString(j));        System.out.println("--------short>>:"+j);        System.out.println("");        i=5;        System.out.println("--------int>>>:"+i);        System.out.println("位移前二进制:"+Integer.toBinaryString(i));        i >>>= 32;        System.out.println("位移后二进制:"+Integer.toBinaryString(i));        System.out.println("--------int>>>:"+i);        System.out.println("");    }}--------int>>:-4位移前二进制:11111111111111111111111111111100位移后二进制:11111111111111111111111111111110--------int>>:-2--------int>>>:-4位移前二进制:11111111111111111111111111111100位移后二进制:1111111111111111111111111111110--------int>>>:2147483646--------short>>:-4位移前二进制:11111111111111111111111111111100位移后二进制:11111111111111111111111111111110--------short>>:-2--------int>>>:5位移前二进制:101位移后二进制:101--------int>>>:5

引申:“<<”运算符与“>>”运算符有什么异同?
“<<”运算符表示左移,左移n位表示原来的值乘2的n次方,经常用来代替乘法操作,例如,一个数m乘以16表示将这个数左移4位(m << 4),由于CPU直接支持位运算,所以位运算比乘法效率高。
与右移不同,左移运算没有有符号和无符号之分,左移时,移出高位的同时在低位补0。
与右移运算符相同的是,当进行左移运算时,如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模,例如左移33位,其实只移动了33 % 32=1位。

4.4.10char型变量中是否可以存储一个中文汉字

在Java语言中,默认使用Unicode编码,即每个字符占用两个字节,因此可以用来存储中文。虽然String是由char所组成的,但是它采用了一种更加灵活的方式来存储,即英文占用一个字符,中文占用两个字符,采用这种存储方式的一个重要作用就是可以减少品所需的存储空间,提高效率。

public class TestChar {    public static void getLen(String str)    {        System.out.println(str+"的长度:"+str.length()+"所占字节数"+str.getBytes().length);    }    public static void main(String[] args)    {        String s1="Hello";        String s2="你好";        getLen(s1);        getLen(s2);    }}运行结果:Hello的长度:5所占字节数5你好的长度:2所占字节数6

在上例中:“Hello”是英文字符,因此所占字节数和字符串长度相同。“你好”字符串长度为2,由于每个字符都占用两个字节,因此总的字节数为4.此方法可用来判断是否包含中文字符。
示例如下:

/** * java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。它包括两个类:Pattern和Matcher  * Pattern : * 一个Pattern是一个正则表达式经编译后的表现模式。 * Matcher : * 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。  *  */import java.util.regex.Matcher;import java.util.regex.Pattern;public class TestChar {    public static void judgeChineseCharactor(String str){        /**         * \u4e00-\u9fa5 代表Unicode编码表中的所有汉字的范围         * [] 代表里面的值出现一个就可以         *          * 所以表达式的意思就是匹配一个或以上的汉字         */        String regEx = "[\u4e00-\u9fa5]";        //判断是否存在中文字符        if(str.getBytes().length == str.length()){            System.out.println("无汉字");        }else{//如果有汉字,找出中文字符             //首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,            Pattern p = Pattern.compile(regEx);            //然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。            Matcher m = p.matcher(str);            while(m.find()){                System.out.print(m.group(0)+"");            }        }    }    public static void main(String[] args){        judgeChineseCharactor("Hello World");        judgeChineseCharactor("Hello 你好");    }}运行结果:无汉字你好
阅读全文
0 0
原创粉丝点击