【第3天】Java数据类型的组成与转换

1 数据类型(单位)★

       Java是一个强类型的编程语言,所有的变量在第一次出现的时候,必须有数据类型。数据类型狭义上分有两种,广义上分有无数种(引用数据类型可自定义,可定义无数种)

1.1 基本(简单)数据类型

       程序里面自带的数据类型,有4类8种。

基本数据类型:

名称booleancharbyteshortintlongfloatdouble
默认值false‘\u0000’(null)(byte)0(short)000L0.0F0.0D
1.1.0 前叙

部分需要注意的类型赋值区间

  • char类型是无符号数据类型,每个字符占用两个字节(16位,【1字节Byte=8位bit】)。所以可赋值区间为16个0—16个1,即0—65535。

  • 整数类型以byte为例,每个字符占用一个字节,这八位分成符号位(1位)+数值位(7位)。需要注意的是出现了符号位,其中的0就有正负之分,化为十进制为0(“正0”)和-128(“负0”),所以取值范围为00000000-11111111,即(-128)—(127)。化为通式即为(-2n-1)—(2n-1-1)。

  • 浮点类型分为符号位 + 幂值位 + 数值位,后面详叙。

  • 基本数据类型之间的转换:范围小的数据类型可以直接给大的数据类型赋值;范围大的数据类型需要强转成小的数据类型,强转时如果数据越界,则截取小类型需要的后几位,见下面例子。需要注意的是char类型和short类型之间永远需要强转,byte类型和char类型之间永远需要强转,后面详叙。

//例子
public class Test1{
	public static void main(String[] args){

		//short:-32768---32767
		short x = 200;

		//byte:-128---127
		int y = (int)x;
		
		/**
			short x = 200 = 128 + 64 + 8 = 0000000011001000
			截取后八位:
			byte y = (byte)x;
			y = 11001000 = -1 - 1 - 2 - 4 - 16 - 32 = -56
		*/
		
		System.out.println(y);
	}
}
  • 调用类时如果遇到类中有方法重载,若传入的参数类型在其中定义的方法的参数中无法找到,自动匹配比传入的参数更大的那个方法参数的方法,如果找不到更大的,报错。
1.1.1 布尔类型(boolean)
boolean flag = true/false;

       用于判断。Java区分大小写,因此boolean只能使用true/false进行赋值,不能使用数字进行赋值。(C++可以,非0值转换为true,0值转换为false)

1.1.2 字符类型(char)
char类型的赋值方式:
			  char x1 = 'a'; //指定字面值的赋值方式	★
			  char x2 = '中';//指定字面值的赋值方式	★
			  //=====================================
			  char x3 = 100;//通过ASCII编码进行赋值 --> 表示d
			  char x4 = '\u4e2d';//通过Unicode编码进行赋值
			  char x5 = '\t';//转义字符

       不同于ASCII码的中文2个字节,英文1个字节。char 底层基于Unicode编码实现的,不区分中英文,一律2个字节(也就是16位【1个字节=8个位】),当使用转义符、Unicode、单个汉字/字母时使用单引号。

常用转义字符

转义符\t\r\b\n
作用TAB键返回本行行首退格键换行

要输入"\"字符时,需要输入两次“\”才可以输出一个“\”。

在System.out打印输出时,单引号中的char类型可能会变成ascii码参与运算,char要想原文本显示必须使用双引号或者升级为String

char类型的转换

       由上图数轴看出,与整数类型相比,char类型是一个无符号的数据类型,与其他整数、浮点类型的数据进行互相转换时,范围大的数据类型转为char时需要强行转换;char转换为同长度的short和比char更小的byte时依然需要强转,后者转换为前者当然也需要强转。需要注意的是当我们拿着一个数字给char类型直接进行赋值的时候,数字有两种理解:

  • 如果这个数字在char类型的取值范围【0-65535】里面的话,数字理解成ascii编码。
  • 如果这个数字不在char类型的取值范围里面,数字理解成int类型。
1.1.3 整数类型
类型名称byteshortintlong
字节(Byte)1248
位(bit)8163264
  • 赋值方式
	int num1 = 67;//通过十进制进行赋值  ★
	int num2 = 067;//通过八进制进行赋值	,可选字符0-7
	int num3 = 0x67;//通过十六进制进行赋值,可选字符0-9和a-f
	int num4 = 0b1011;//通过二进制进行赋值,可选字符0和1,这种写法在jdk7.0及以后使用
  • 需要注意的是:

    • 输出时,之前定义的非十进制的数字都要转换为以十进制输出,定义的其他进制类型转换为十进制后要确保在这个数据类型的范围中。
    • 如果要在程序中不定义类型直接使用一个整数,默认数据类型为int。
    • long类型的结尾要加上L,如果"long i = 1",则指的是将int值1赋给变量i。
    • 当数值超出int类型最大边界的时候,注意使用long类型。
    • 如果将浮点数存入整数类型,小数部分直接消掉。
  • 整数类型(十进制)与存储时形态(二进制)之间的转换(非重点)

存储时首位一定是符号位,用来分辨正负数字,剩下的位为数值位。这里为了好表示,以byte类型为例,其他类型同理。



正数:
	byte x = 55 = 32 + 16 + 4 + 2 + 1 = 00110111



负数:需要使用补码表示*
	当一个整数类型的二进制位上全是1的话 表示该类型十进制的-1,如:
	byte:11111111 : -1
	short:1111111111111111 : -1
	int:11111111111111111111111111111111:-1

可以这么理解
	     11111111:x
          +	    1
          -----------
             00000000:0		x + 1 = 0  x = -1

所以:
	byte x = -59 = -1 - 58 = -1 - 32 - 16 - 8 - 2 = 11000101

*负数需要使用补码表示的原理 作者:leonliu06

1.1.4 浮点类型
类型名称floatdouble
字节(Byte)48
位(bit)3264
  • 需要注意的是:

    • 如果要在程序中不定义类型直接使用一个双精度浮点型数据,默认数据类型为double。
    • float后面一定要加一个F,double后面可以加D。
    • float为单精度浮点,存一位小数;double为双精度浮点,存两位及多位,更精确。
public class Test2{
   public static void main(String[] args){
   
   	float x = 2.0F;
   	float y = 1.1F;
   	System.out.println(x - y); // ------>0.9

   	double a = 2.0;
   	double b = 1.1;
   	System.out.println(a - b);// ------>//0.899999

   }
}
  • “2E3”的意思是2*103,科学计数法的表示方法。

  • 浮点类型和存储时形态(二进制)之间的转换(非重点)

    • float:符号位(1位) + 幂值位(8位) + 数值位(23位)
    • double:符号位(1位) + 幂值位(11位) + 数值位(52位)
存储时首位一定是符号位,用来分辨正负数字,中间为幂值位,最后为数值位。这里以float类型为例,double类型同理。

	float x = 45.25F;

S1 将上面的两个部分全部转换成二进制
		a:整数:45 = 32 + 8 + 4 + 1 = 101101
		b:小数:0.25 = 01
		小数算法:不断*2取整数,直到得到1.0
					0.25 * 2 = 0.5
					0.5 * 2 = 1.0
		得结果:a + b = 101101.01

S2 将上面的结果转换成二进制的科学计数法
		101101.01 -> 1.0110101 * 2^5

S3 得到2的次数后,将次数与2^(n-1)-1相加,即将得数化为2^(n)+X的形式得到二进制
         (这里的n指的是幂值位位数)
         127 + 5 = 132 = 128 + 4 = 10000100
         
S4 对号入座
		符号位(1位) + 幂值位(8位) + 数值位(23位)
		  0	       10000100       01101010000000000000000

	结果:01000010001101010000000000000000

如果算负数,只需要将整数位按照前面整数类型的算法算出即可,其他同理。
  • 面试题:将17.1F化为存储时形态
	float y = 17.1F;
	
S1 将上面两个部分全部转换成二进制
		17:16 + 1 = 10001
		0.1:00011001100110011 以[0011]循环
		0.1 * 2 = 0.2
		0.2 * 2 = 0.4
		0.4 * 2 = 0.8
		0.8 * 2 = 1.6
		0.6 * 2 = 1.2
		0.2 * 2 = 0.4
		0.4 * 2 = 0.8
		0.8 * 2 = 1.6
		....
		
	结果:10001.000110011[0011]
		
		
S2 将上面的结果转换成二进制的科学计数法
		10001.000110011[0011] -> 1.0001000110011[0011] * 2^4
		
		
S3 得到2的次数后,将次数与2^(n-1)-1相加,即将得数化为2^(n)+X的形式得到二进制
         (这里的n指的是幂值位位数)
         127 + 4 = 128 + 2 + 1 = 10000011
         
          
S4 对号入座
		符号位(1位) + 幂值位(8位) + 数值位(23位)
		  0	       10000011       00010001100110011001100
		  	  
	结果:01000001100010001100110011001100
  • 由上面的面试题可以看出,浮点类型的小数在存储时会出现数值位无限循环情况,进而导致运算时出现精度问题,下面的例子:
import java.math.*;
public class Test3{
	public static void main(String[] args){
		System.out.println(2.0 - 1.1);//--------->输出0.8999999999999
	}
}

为什么会出现0.899999999的情况?

       java中任何一个整数都可以用二进制精确的表示出来,但是不代表任何一个浮点数也可以在有限的位数里面表示出来。上面的1.1在底层存储的时候,出现了数值位的截取,导致数值不正确。

如何解决?

  1. 数值使用较小单位,转换为整数存储。如数值扩大100倍,也就是单位缩小100倍。
  2. 使用java.math工具类中的BigDecimal类进行精确运算。
import java.math.*;
public class Test4{
	public static void main(String[] args){
		double num = 1.0;
		System.out.println("double:");
		for(int x = 1;x <= 10;x++){
			num = num + 0.1;
			System.out.println(num);
		}
		
		BigDecimal b1 = new BigDecimal("1.0");
		BigDecimal b2 = new BigDecimal("0.1");
		System.out.println("\n" + "\n" + "BigDecimal:");
		for(int x = 1;x <= 10;x++){
			//加法
			b1 = b1.add(b2);
			//减法
			//b1 = b1.subtract(b2);
			//乘法
			//b1 = b1.multiply(b2);
			//除法
			//b1 = b1.divide(b2);
			System.out.println(b1);
		}
	}
}

执行结果:
在这里插入图片描述

2 引用数据类型(程序员自己开发的数据类型,或官方给的工具包中的类)

       包括类、接口类型、数组类型、枚举类型、注解类型

       后续会频繁使用,不展开写。常见的有java.lang包中的String字符串类,这个包不需要import调用,直接可以声明类使用,默认值为null。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值