Java基础之数据类型

数据类型的由来

由于Java是一种强类型语言,声明一个变量必须规定数据类型(基本数据类型、引用数据类型)

img

基本数据类型的分类(四类八种)

  • 整数型

    • byte
    • short
    • int
    • long
  • 浮点型

    • float
    • double
  • 布尔型

    • boolean
  • 字符型

    • char

整型

占用字节范围
byte 字节1-128~127
short 短整型2-2^15 - 2^15-1
int 整型4-2^31~ 2^31-1
long 长整型8-2^63~ 2^63-1
2:要想表示更大范围的整数,可以使用BigIntegerBigDecimal
3:整型默认为int4:声明long型,需要在数字后面加L或者l
5:bit是计算机中最小的存储单位。byte是计算机中基本的存储单位。1 byte = 8 bit 
6int a = 1L;//编译出错,long类型不能转为int类型
	 long b = 1;//编译通过
7byte b = 1;//编译通过,没出出现向下转型的编译问题是因为:编译器会自动检查,数字是否超出范围,是否会造成精度丢失,
								如果不会造成精度丢失,会自动进行类型转换。
8int a = 1;
   byte b = a; //编译失败,a是int类型,在内存中是按4字节存储空间,因此4字节空间不能存入byte范围
   							因此,如果是按变量赋值,直接判断类型范围。
9short s1 = 1;
   s1 = s1 + 1; // 编译不通过,错误,s1+1 是int 类型,需要强转才能赋值给s1;
   s1 += 1; // 可以编译通过。s1 += 相当于 s1 = (short)(s1+1),其中有隐含的强转,对于 += 是Java 提供的运算符,编译器会对它进行转换处理      

1.为什么byte的范围是-128~127?

   计算机中运算时是以补码的方式运算的,二进制的最左侧为最高位,0表示正数,1表示负数
   正数的最大二进制是01111111,正数的补码还是本身,因此正数的补码是:
   0*2^8 + 1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 = 127 
   负数最小的二进制原码是10000000,负数的补码=反码+1,
   负数的反码=(原码符号位不变,其余位数取反)。最小的二进制负数补码是(原码10000000->
   反码11111111->补码-127+1) = -128)
   总结:二进制8位最大值是01111111转换为10进制是127
   二进制8位的最小值10000000转换位10进制是-128,因此byte的取值范围是-128-127 

浮点型

占用字节范围
float 单精度4
double 双精度8
1:浮点型默认是double类型
2:声明float型,必须加上f或者F
3:folat f = 1.1;//编译失败,1.1默认是double类型
4:double d = 1.1f;//编译通过,1.1f是float型
5:double的精度高于float,保留的小数点的位数也更多
6:0.1*3 == 0.3 //false
   0.1*2 == 0.2 //true
7:为什么说 double 是双精度,float 是单精度呢?
   float 有效位数是 6 ~ 7位,double 有效位数是 15 位,有效位数的意识是:小数点后有几位。
   double 的数值精度是 float 的 2 倍,因此,double 是双精度,float 是单精度。

浮点型数据存放形式:符号位+指数位+尾号位

img

sign:符号位,用来表示正负数,0表示正数,1表示负数

exponent:指数位,用来表示指数,实际要加上偏移量

fraction:小数位,用来表示小数,不足位数补0

从这里看出,指数位决定了大小范围,小数位决定了计算精度。当十进制转化为二进制后,得到的尾数位数有可能很长甚至无限长。所以当浮点格式存储数字时,实际存储的尾数是被截取或执行舍入后的近似值,这就解释了浮点数计算不准确的问题,因为近似值和原值是有差异的。

解决方式:

1)

​ double d1 = 1 - 0.9; // 0.09999999999999998

​ double d2 = 0.1;

​ d1 == d2 ;// false

​ 对于运算后的小数之间比较,使用Math.abs(d1-d2) == 0 ;// 判断是否相等

2)使用BigDecimal.compareTo

字符型

占用字节范围
char 字符20 - 65535
1:char可以数字、字母、汉字、制表位
2:将一个数字赋值给char型,当输出这个变量值时,会输出数字代表的unicode码对应的字符。
3:char c = 97;//a
   char c1 = 'a';//默认输出是unicode码对应的字符,那么应该(int)c1 = 97
4:int a = 'a' + 10; //编译器会先将'a'转为97   
5:char c = 'a' + 10; 
   System.out.print((int)c);//97+10
   System.out.print(c);//107对应的unicode码
6:字符型存储到计算机中的过程:将字符对应的整数找出来,然后转化为二进制存储到计算机
   读取的过程:将数字取出,转化为unicode对应的编码显示
7:字符编码:
   ASCII编码是对英语字符和二进制之间的关系做了统一规定,每一个字符使用1个字节表示的,
   使用字节中的低7位表示,最前面一位表示为0,一共有128个字符,
   实际上一个字节可以表示256个字符。但是不能表示中文
   Unicode固定大小的编码编码使用2个字节表示字符,字母和汉字都占2个字节,不会出现乱码问题
   Unicode码兼容Ascii码
   Utf-8大小可变的编码字母使用一个字节,汉字使用3个字节,UTF-8码是对Unicode码的改进,可变编码
   gbk字母1字节,汉字2字节
   gb2312也可以表示汉字(gb2312<gbk)
   big5码可以存储繁体中文

boolean

占用字节范围
boolean1true或者false
1:只允许取true或者false,无null
2:boolean的默认值是false

基本数据类型自动转换

img

1:有多种数据类型混合运算的时候,系统会自动将数据类型都转化为容量最大的那个
   int a = 1;
   float f = a + 1.1; //编译异常,因为a+1.1结果是double类型
   float f = a + 1.1f;//正确
   double d = a + 1.1;//正确
   int a = 1.1;//编译失败
2:byte、short分别不能和char进行自动转换。
   byte b = 1;
   char c = b; // 编译错误
   byte b = 'a';//可以直接把char类型的字符赋值给byte,但是不能直接赋值变量
   
3:byte、short、char三者之间可以进行运算,不管是单独结算还是混合运算,会先自动转为int
   byte b = 1;
   short s = 2;
   short a = b+s;//编译错误,b+s结果是int类型
   int a = b+s;//正确
   byte b2 = 2;
   byte b3 = b+b2;//编译错误,b+b2结果是int类型
  
 4: 为什么long占8字节,取值范围反而比4字节的float小?
 因为浮点数和整数在内存中的存储机制不同,浮点数是符号位+指数位+小数位组成 

基本数据类型强制转换

1:强制转换是自动转换的逆过程。将容量大的数据类型转换为容量小的数据类型,
   使用时要加上强制转换符()。但可能会造成精度丢失
2:int a = (int)1.9;//1 造成了精度丢失
   byte b = (byte)2000;// 造成了溢出
3:byte b = 1;
   b = b +1; //错误,int->byte
   b = (byte)(b+1);//正确。
4:byte b = 1;
   short s = 2;
   short s = s + b;
5:double d = 1/2; // 0.0,1/2由于都是int类型,0.5转int是0,0转化为double = 0.0
   double d = 1/2d;//0.5
 +1; //错误,int->byte
   b = (byte)(b+1);//正确。
4:byte b = 1;
   short s = 2;
   short s = s + b;

基本数据类型和引用数据类型的区别

在内存中存储的位置不同

基本数据类型存储于栈中,引用数据类型存储于堆中,栈中存储的是它的地址
在这里插入图片描述

传递方式不同

基本数据类型在调用方法时,是按照值传递的

//基本数据类型作为方法参数被调用
public class Main{ 
    public static void main(String[] args){ 
           int msg = 100; 
           System.out.println("调用方法前msg的值:\n"+ msg); //100 
           fun(msg); 
           System.out.println("调用方法后msg的值:\n"+ msg); //100 
    } 
    public static void fun(int temp){ 
           temp = 0; 
       } 
} 

在这里插入图片描述
引用数据类型是引用传递

//引用数据类型作为方法参数被调用 
class Book{ 
String name; 
double price; 
public Book(String name,double price){
       this.name = name; 
       this.price = price; 
} 
public void getInfo(){ 
         System.out.println("图书名称:"+ name + ",价格:" + price); 
         } 
         public void setPrice(double price){ 
                 this.price = price; 
          } 
 } 
public class Main{ 
      public static void main(String[] args){ 
                Book book = new Book("Java开发指南",66.6); 
                book.getInfo(); //图书名称:Java开发指南,价格:66.6 
                fun(book); 
                book.getInfo(); //图书名称:Java开发指南,价格:99.9 
           } 
          public static void fun(Book temp){ 
               temp.setPrice(99.9); 
      } 
 } 

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值