JAVA基础知识点(1)_基本数据类型

@TOC

8个基本数据类型

Java中基本数据类型有8个,分别是byte, short, int, long, char, float, double, boolean。
按照类型划分,8种基本数据类型为:
4种整型:byte,short,int,long
2种浮点类型:float,double
1种Unicode编码的字符单元的字符型:char
1中Boolean类型:boolean

基本数据类型的取值范围

其名称、位数、默认值、取值范围及示例如下表所示:
基本数据类型大小和范围
注意:char字符的默认值是空,不是null,输出的时候 是一个空的字符

位数问题:
Java中每字节是8位,无论是汉字还是英文字母都是用Unicode编码来表示的,一个Unicode码是16位,每字节是8位,所以一个Unicode码占两字节。

boolean布尔值占用位数问题

直接上结论:
boolean的大小JVM规范并没有指定,在java虚拟机规范中,boolean单独存在占4字节,在boolean数组中占1字节。具体还要看虚拟机实现是否按照规范来,所以1个字节、4个字节都是有可能的。
找了一些资料和网上的说法,最标准的说法是下面两种:
1,单个布尔类型变量使用 int 值来表示,而int在java中是4个字节表示,是32位。
2,布尔数组采用 byte 数组来表示,数组时,每一个boolean在JVM中占一个字节,是8位。
存在两种字节的原因是:
在《Java虚拟机规范》一书中的描述:“虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位”。也就是说JVM规范指出boolean当做int处理,也就是4字节,boolean数组当做byte数组处理,boolean类型占了单独使用是4个字节,在数组中是确定的1个字节
下图是《Java虚拟机规范.pdf》中的内容在这里插入图片描述

对于boolean类型数组的测试,有下面的Java代码,该部分代码参考stackoverflow,(What is the size of boolean variable in Java)

package com;
public class booleanSize {
    private static final int SIZE = 100000;
     public static void main(String[] args) throws Exception
     {
         LotsOfBooleans[] first = new LotsOfBooleans[SIZE];
         LotsOfInts[] second = new LotsOfInts[SIZE];
         System.gc();
         long startMem = getMemory();
         for (int i=0; i < SIZE; i++){
             first[i] = new LotsOfBooleans();
         }
         System.gc();
         long endMem = getMemory();
         System.out.println ("Size for LotsOfBooleans: " + (endMem-startMem));
         System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));
         System.gc();
         startMem = getMemory();
         for (int i=0; i < SIZE; i++)
         {
             second[i] = new LotsOfInts();
         }
         System.gc();
         endMem = getMemory();
         System.out.println ("Size for LotsOfInts: " + (endMem-startMem));
         System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));
         // Make sure nothing gets collected
         long total = 0;
         for (int i=0; i < SIZE; i++)
         {
             total += (first[i].a0 ? 1 : 0) + second[i].a0;
         }
         System.out.println(total);
     }
     private static long getMemory()
     {
         Runtime runtime = Runtime.getRuntime();
         return runtime.totalMemory() - runtime.freeMemory();
     }
}
class LotsOfBooleans
{
    boolean a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    boolean b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    boolean c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    boolean d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    boolean e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}
class LotsOfInts
{
    int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    int c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    int d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    int e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}

我使用的是 jdk-1.6版本,运行结果如下图, int是boolean的4倍多一点,也就是基本上4倍,由此,基本上可以说,Boolean类型数据在数组中占1字节。

在这里插入图片描述

对于单个boolean来说,虚拟机为什么要用int来代替boolean呢?为什么不用byte或short,这样不是更节省内存空间吗?
使用int的原因是,对于32位处理器(CPU)来说,一次处理数据是32位,32 位 CPU 使用 4 个字节是最为节省的,哪怕你是 1 个 bit 他也是占用 4 个字节。因为 CPU 寻址系统只能 32 位 32 位地寻址,具有高效存取的特点。
(PS:猜测一下,由于32位处理器于1985年推出,并逐渐成为主流,直到现在仍然有很多32位处理器在使用,而Java正式发布的时间是1995年,为了迎合大众,Java使用的也是32位处理器,所以boolean类型默认为int类型,并且Java中有隐示转换,byte、short、char类型的数据都是直接自动转换到int类型,对于32位的处理器来说,低于32位的数据类型(像byte、short、char)直接转换成32位(像 Int)更方便,后期就不需要在不够补齐了(二进制中的补齐),这样JVM的速度就会更快,像高于32位的数据类型,也就是64位的数据,会分为两个32位进行执行。)

关于类型变量占用字节大小问题

类型变量占用的字节大小是由语言标准和编译环境来决定的,如果在语言标准中定义了的话,那么就由标准来决定,否则就由编译环境来决定。

例如:JAVA中默认采用的是unicode编码, 所以char是占用两个字节;而在C++中是占用1个字节。
在VC中int是占用4个字节,而在TC 中是占用2个字节,这是在语言标准中没有明确定义这个大小的,所以由编译环境来决定。

隐式转换和显示转换

在java中,隐式转换又称为 自动转换,取值范围从小的数据类型 转向 取值范围大的数据类型,由系统负责自动转换。
byte、short、char类型的数据都是直接自动转换到int类型。
隐式转换优先级
byte,short,char -> int -> long -> float -> double

显式转换又叫强制转换,即取值范围大的数据类型 转向 取值范围小的数据类型 。
转换规则为: a = (a的数据类型)b。
注意:**强制转换可能会损失精度。**比如double类型的 5.8转换为int类型,结果为5,小数点后的值没了。

int a = 2;
double b = 1.2;
// 由 a 向 b 转换, 取值范围小的转向取值范围大的,为隐式转换
b = a;
System.out.println(b);
int a1 = 3;
double b1 = 5.8;
// 由 b1 向 a1 转换, 取值范围大的转向取值范围小的,为强制转换(显示转换)
a1 = (int) b1;
System.out.println(a1);

输出结果为
在这里插入图片描述
注意:此时 b1转换为a1后的值是 5,不再是5.8,涉及强制转换的代码中,一定要确认好转换前后的类型,防止出现数据精度丢失的情况。

类型转换中,要遵守以下规则:
1、八种基本数据类型中,除 boolean 类型不能转换,剩下七种类型之间都可以进行转换
2、如果整数型字面量没有超出 byte,short,char 的取值范围,可以直接将其赋值给 byte,short,char 类型的变量
3、小容量向大容量转换称为自动类型转换,容量从小到大的排序为:byte < short(char) < int < long < float < double,其中 short和 char 都占用两个字节,但是char 可以表示比short更大 的正整数
4、大容量转换成小容量,称为强制类型转换,编写时必须添加“强制类型转换符”,但 运行时可能出现精度损失,谨慎使用
5、 byte,short,char 类型混合运算时,先各自转换成 int 类型再做运算
6、 多种数据类型混合运算,各自先转换成容量最大的那一种再做运算

基本数据类型的定义

在方法中,定义变量的格式为
变量类型 变量名 变量初始值;
具体如下:

public class Test {
public static void main(String[] args) {
boolean flag = true;
char yeschar = 'y';
byte finbyte = 30;
int intvalue = -70000;
long longvalue = 200l;
short shortvalue = 20000;
float floatvalue = 9.997f;
double doublevalue = 1.117;
}
}

在类中,定义变量可以不赋初始值,因为此时还没有初始化对象

public class Test {
 static byte b;
 static short s;
 static int i;
 static long l;
 static float f;
 static double d;
 static char c;
 static boolean bo;
 }

注意: float的赋值带有一个 F或者f的符号,这是因为java中规定,任意一个浮点型数据默认当做double来处理,如果想用float类型,在初始化值后面添加F/f。同理long类型也一样。long类型默认被当做int类型处理。如果希望数据被当做long类型处理,需要在“数值”后面添加L/l。

基本数据类型

一、字符型:char
1、char占用两个字节,har的取值范围:[0~65535] ,参考最上面取值。
2、char类型的定义时要使用单引号括起来。即 char a = ‘a’;
3、char可以存储一个汉字。例 char c1 = ‘国’;
注意:
①不能使用双引号,双引号是定义字符串的。字符串无法转换为char类型
②如果是数字0,加上单引号,输出的是文字0,是一个字符。
③单引号中,只能有一位数字,两位或者带有小数点的均报错。
二、整数型
byte 1个字节
short 2个字节
int 4个字节
long 8个字节
具体大小参看上面表格。
整数型涉及不同的进制,常用的是十进制。也有二进制、八进制、十六进制。

// 十进制
int a1 = 10;
System.out.println("十进制输出结果,a1=" + a1);

// 八进制
int b1 = 010;
System.out.println("八进制输出结果,b1=" + b1);

// 十六进制
int c1 = 0X10;
System.out.println("十六进制输出结果,c1=" + c1);

// 二进制(jdk1.8的新特性,低版本不支持)
int d1 = 0b10;
System.out.println("二进制输出结果,d1=" + d1);

默认输出的是
十进制输出结果,a1=10
八进制输出结果,b1=8
十六进制输出结果,c1=16
二进制输出结果,d1=2

相当于把不同进制转换为十进制。
三、浮点型:float double
1、float 4个字节 double 8个字节 ,取值范围参考上面表格。
2、float是单精度 double是双精度,double更精确。
比如说,10/3,如果用float来存储的话可能是:3.3333,如果用double来存储的话,可能是3.33333333
但需要注意的是**,如果存储数据涉及金额方面,使用 引用数据类型BigDecimal**,比如银行和财务等行业,不使用float / double,在java中提供了一种精度更高的类型,java.math.BigDecimal(不是基本数据类型,是引用数据类型。)
3、float和double存储数据的时候都是存储的近似值,例如无限循环小数3.33333…。但计算机的内存有限,用一个有限的资源表示无限的数据,只能存储近似值。
常见的浮点数 3.14159 1E10

注意:
任意一个浮点型都比整数型空间大。(和java底层有关)
比如:long类型占用8个字节,float占用4个字节,float的容量大。
(PS:浮点型和整数型区别:
整型数在计算机底层采用补码的形式表示,除去首位的符号位,剩余的位数即表示数值的范围。浮点数在计算机中则是实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,用以近似表示任意某个实数。关于这一部分内容较多,可以在站内搜索 计算机组成原理之浮点数,讲解的很详细)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值