Java基本数据类型和运算符面试温习

前言

java是一门强类型语言,其表现为两个方面:一是变量必须先声明其类型方可使用,二是变量一旦确定类型后便不可更改(另一个角度则是:指定类型的变量只能接受与之相匹配的类型),java的数据类型包含基本数据类型和引用数据类型。

基本数据类型如下图所示:
Java基本数据类型和运算符面试温习_第1张图片
除此之外还有一个特殊的引用类型null,这种类型没有名称,所以无法声明null类型的变量,但是它可以转换任意一个引用数据类型。

整数类型

整数类型在java中声明了byteshortintlong四种。

  • byte
    一个byte类型整数占1个字节也就是8个比特位,其取值范围为 − 2 7 -2^{7} 27 2 7 − 1 2^{7} - 1 271
  • short
    一个short类型整数占2个字节也就是16个比特位,其取值范围为 − 2 15 -2^{15} 215 2 15 − 1 2^{15} -1 2151
  • int
    一个int类型整数占4个字节也就是32个比特位,其取值范围为 − 2 31 -2^{31} 231 2 31 − 1 2^{31} -1 2311
  • long
    一个long类型的整数占8个字节也就是64个比特位,其取值范围为 − 2 63 -2^{63} 263 2 63 − 1 2^{63} -1 2631
    需要注意的是int类型的数据是最常用的,除此之外它也是整数类型的默认类型。java的整数类型分别有4种表现形式:二进制八进制十进制十六进制,其中二进制数据以0b或者0B开头;八进制数据以0开头;十六进制数据以ox或者0X开头。下面用代码表示以上数据类型。
// 10进制
int a = 10;
// 二进制 0b1010
String s = Integer.toBinaryString(a);
// 16进制 0xa
String s1 = Integer.toHexString(a);
// 8进制数据 012
String s2 = Integer.toOctalString(a);
System.out.println(s + "\n" + s1 + "\n" + s2);

浮点型

java定义了2种浮点型:floatdouble。其中float占4个字节;double占8个字节,double是浮点型常用的数据类型,除此之外它也是浮点类型默认的类型。声明一个float类型的数据需要在数字后面加f或F。

	// 声明float类型的数据
   float b = 5.2f;
   // 声明double类型的数据
   double c = 3.0;

学习还发现了一个有意思的新特性无论是整数类型还是浮点型都可以是用下划线区分有多少位,这在分辨二进制整数类型特有有用。

   int d = 0B1010_1011_1110_0010_1010_10;
   double e = 3.14_15926_13;

字符类型

字符型表示单个字符用\‘表示,世界各个国家都有很多字符,为了容纳这么多字符java采用16位(65535)的Unicode字符集进行编码。char类型有以下三种表现形式:

  • 单个字符
    通过用(‘’)表示单个字符,如‘a’。
  • 转义字符
    ‘\n’、'\t'、'\r'分别表示换行符、制表符、回车符
  • 用Unicode表示字符型值
    其中在前256个字符(’\u0000’至’\u00FF’)和ASCLL码表中的字符完全一致,还需要注意的是如果一个数是int类型(值在0-65535)赋值给char类型的变量,java会自动将int类型数据当成char类型进行处理。
// 将int类型的数组赋值于char类型的变量a
 char num = 97;
 // 输出a,对照ASCLL码表:a字符对应的10进制整数类型刚刚好是97
 System.out.println(num);

java没有提供表示字符串的数据类型,而是通过String类进行定义的。

  // 定义字符串类型str	
  String str = "hello java";
  // 将字符串类型转字符类型数组
  char[] chars = str.toCharArray();
  // 输出[h, e, l, l, o,  , j, a, v, a]
  System.out.println(Arrays.toString(chars));

布尔类型

程序生涯中,注定和boolean类型数据打过很多交道。无论是在循环结构、条件判断语句你都会经常见到它。

   // 定义变量flag
   boolean flag1 = false;
   boolean flag2 = true;

基本数据类型转变

程序中经常有各种转换,java中有两种转换一个向上转换(也叫自动类型转换)、一种就是向下转换(也叫强制类型转换)。
  当将一个小的数据类型转换大的数据类型,我们称之为自动类型转换,否则就是强制类型转换。主要注意的是后者可能会出现精度损失,前者则不会造成精度损失。就如有两个水杯其中大杯500M容量大的1L的容量,将500Ml小瓶水放入大瓶没有问题。
Java基本数据类型和运算符面试温习_第2张图片

  • 自动类型提升
	// 定义byte类型的数据
   byte a = 25;
   // 将byte类型的数据赋值给int类型。(a此时自动类型提升为int类型数据)
   int b = a;

上面定义了一个byte类型的a以及int类型的b,此时我们定义一个byte类型的c。

 byte c = a + 1;

此处编译器将会提升错误,原因是等号右边byte类型数据与int类型的数据运算结果是int类型数据,int类型的数据是不能直接赋值给byte类型数据,解决这个问题就是使用强制类型转换。

       byte c = (byte) (a + 1);
  • 强转溢出问题
    如下代码片段所示:int类型130强转byte变为-126,这就是典型的溢出问题。
  int a = 130;
  byte b = (byte)a;
  // 输出-126
  System.out.println(b);

如下图将展示整个转换过程,以及解释为什么会造成溢出。
Java基本数据类型和运算符面试温习_第3张图片
int类型为4个字节(32个比特位) byte类型为1个字节(8个字节) ,当将int类型数据强制byte数据类型会砍掉前24位只保留右8位,其中最左边为符号位。我们都知道计算机存储数据机制:正数存储的二进制原码,负数存储的是二进制的补码,补码是负数的绝对值反码加1。最后负数的原码为11111110转换成10进制位为-( 2 6 2{^6} 26+ 2 5 2{^5} 25+ 2 4 2{^4} 24+ 2 3 2{^3} 23+ 2 2 2{^2} 22+2)=-126。

运算符

java目前提供的运算符有以下几种:、算术运算符、赋值运算符、比较运算符、逻辑运算符、位运算符、类型运算符。

  • 算术运算符
    Java支持加、减、乘、除、取余操作。
    int a = 130;
    double b = 3;
    // 输出133.0
    System.out.println(a + b);
    String c = "1";
	// 任何类型的数据与字符串相加都将会得到字符串类型数据
    System.out.println(a+b+c); // 输出1331
	// a-b 输出127.0
    System.out.println(a - b);
    // a*b 输出390.0
    System.out.println(a * b);
    // a/b 输出43.333333333333336
    System.out.println(a / b);
    // a%b 输出1.0
    System.out.println(a % b);

如果对上面操作有更严谨的操作比如保留几位小数点,四舍五入都可以通过BigDecimal类进行实现。

  BigDecimal a = new BigDecimal(130);
  BigDecimal b = new BigDecimal(3);
  // a除以b四舍五入保留两位小数 输出43.33
  System.out.println(a.divide(b, 2,BigDecimal.ROUND_HALF_UP));

java还提供了java.lang.Math提供其他运算符计算如:开方、平方、绝对值、对数等。

	// 求2的三次方
   System.out.println(Math.pow(2, 3));
   // 16开平方
   System.out.println(Math.sqrt(16));
   // 求-15绝对值
   System.out.println(Math.abs(-15));
   // 求对数
   System.out.println(Math.log(Math.E))

除此之外还有运用广泛的自增和自减运算符:++或者–在变量前:即(++i、–i)先将变量自增或者自减然后在参与运算,++或–在变量后:(即i++、i–)先将变量参与运算然后在自增或者自减,如下面一个简单的示例:

  • 面试题一
int i = 1;
// 先将i的赋给j,所以j=1,然后i自增=2
int j = i++;
// 2 +3 * 3=11
int k = i + ++i * i++;
  • 面试题二
int i = 0;
// j=0,i=1
int j = i++;
// j=1,z=1
int z = ++j;
System.out.println(i + j + z++);
// i=1,j=1,z=2
System.out.println("i="+i+",j="+j+",z="+z);

赋值运算符

赋值运算符是将等号右边的值赋值给左边定义的变量值。

	int a = 1;
	double b =3.5;
	boolean c = false;

位运算符

java支持的位运算符有以下几种。

  • & 按位与
    当两个数都为1才返回1。
  • | 按位或
    当两个位有一个为1就返回1。
  • ~ 按位非
    单目运算符将每个位都按位取反(包括符号位)。
  • ^ 按位异或
    当两位相同返回0,否则返回1。

下面以程序和图说明以上位运算符运算问题(为了方便将int类型前24位0砍掉),加深对位运算的理解。

// 输出1
System.out.println(3 & 5);
// 输出7
System.out.println(3 | 5);
// 输出-6
System.out.println(~5);
// 输出6
System.out.println(3 ^ 5);
// 输出1,20,1
System.out.println((5 >> 2) + " " + (5 << 2) + " " + (5 >>> 2));

3&5=1 计算如下
Java基本数据类型和运算符面试温习_第4张图片
3|5计算如下
Java基本数据类型和运算符面试温习_第5张图片
~5计算如下
Java基本数据类型和运算符面试温习_第6张图片
3^5计算如下
Java基本数据类型和运算符面试温习_第7张图片
除了上面4个常见的运算符还有<<>>>>> 左移、右移、无符号右移,其中>>>>>的区别是:两者都是将位进行右移,但是前者空出来的符号位以原来的符号位保存一致,而后者空出来的符号位始终为0。从另一个角度说左移n位实际就是乘以 2 n 2{^n} 2n,而右移则是除以 2 n 2{^n} 2n

比较运算符

这块比较简单就不在说明。

逻辑运算符

逻辑运算符常操作2个布尔变量,一共右以下6种。

  • &&
    短路与:当两个变量都为true才返回true,与此同时当第一个变量为false第二个变量则不在判断直接返回false。

  • &
    与:当两个变量都为true才返回true,与此同时当第一个变量为false第二个变量仍然继续判断然后在返回false,没有短路的作用。

  • ||
    短路或:当两个变量只要有一个为true则返回true且第一个如果为true就不在继续判断第二个变量直接返回。

  • |
    -短路或:当两个变量只要有一个为true则返回true且第一个如果为true第二个变量仍然继续判断。

  • !
    非:当变量为false则返回true,变量为true则返回false。

  • ^
    或:当两个布尔变量都不同则返回true,否则返回1。

  • 经典面试题

public static void main(String[] args) {
        int x = 0;
        int y = 0;
        int k = 0;
        for (int z = 0; z < 5; z++) {
            if ((++x > 2) && (++y > 2) && (k++ > 2)) {
                x++;
                ++y;
                k++;
            }
        }
        System.out.println(x + "," + y + "," + k);
    }

输出结果为:5,3,1此处分析详情请参考:面试题详解。

三元运算符

三元运算符也叫三母运算符,其实有些时候可以将if else语句简化成三元运算符。

    String str = 5 == 5 ? "等于" : "不等于";
   // 等价于
   String str = null;
   if(5==5) {
		str ="等于";
	} else {
		str ="不等于";
	}

基本数据类型面试题

下面是记录了一些经典的常见的数据类型和运算符相关的面试题,希望对各位出去面试遇到笔试能有所帮助。

 // TODO *=,+=都要隐式类型转化,/=
        int i = 1;
        // TODO 相当于 i=(int)(i*0.1)
        i *= 0.1;
        System.out.println(i);
        i++;
        System.out.println(i);
        int m = 3;
        int n = 2;
        // TODO 相当于n=(int)(n*m++)
        n *= m++;
        System.out.println("m=" + m);
        System.out.println("n=" + n);
        int x = 10;
        // TODO x=x+ x++ + ++x
        x += x++ + ++x;
        System.out.println("x=" + x);

        int z = 1;
        int y = 1;
        if (z++ == 2 && ++y == 2) {
            z = 7;
        }
        System.out.println("z=" + z + ",y=" + y);

        // TODO 判断类型
        boolean o = true;
        boolean p = false;
        short q = 42;
        if (p == true)
            if (q++ == 42 && p == true) q++;
        if ((o == false) || (++q == 45)) q++;
        System.out.println("q=" + q);
        int r = Integer.MAX_VALUE;
        //TODO 一定范围内<< 相当于乘以2的幂,>> 相当于除以2的次幂
        System.out.println("r<<21=" + (r << 60));
        // TODO >>> 无符号右移动,最高位用0补,因为一般二进制首位是符号位(0代表正数,1代表负数)
        System.out.println("r<<21=" + (r >>> 12));

        // TODO 任何一个数一个数在异或相同数相当于本身无任何变化
        System.out.println(1 ^ 2 ^ 2);

输出结果如下:

0
1
m=4
n=6
x=32
z=2,y=1
q=43
r<<21=-268435456
r<<21=524287
1

你可能感兴趣的:(Java基础)