第四章 数据类型

 

1 数据类型

1.1 数据类型有什么用?

数据类型用来声明变量,程序在运行过程中根据不同的数据类型分配不同大小的空间。
int i = 10;
double d = 1.23;
i变量和d变量类型不同,空间大小不同

1.2 数据类型在java语言中包括两种

第一种:基本数据类型
基本数据类型又可以划分为4大类8小种:
第一类:整数型
byte, short, int, long
第二类:浮点型
float, double
第三类:布尔型
boolean:只有两个值true和false,true表示真,false表示假
第四类:字符型
char:java中规定字符型字面量必须使用单引号括起来。
8小种:
byte, short, int, long
       float, double
       boolean
       char

第二种:引用数据类型
字符串型String属于引用数据类型。String字符串不属于基本数据类型
java中除了了基本数据类型之外,剩下的都是引用数据类型,引用数据类型后期面向对象的时候才会接触。

1.3 八种基本数据类型

整数型:byte, short, int, long有什么区别?
浮点型:float和double有什么区别?
区别:占用的内存空间大小不同。


关于计算机存储单位?
计算机只能识别二进制。(1001010010100...)
   1字节 = 8bit(比特) --> 1byte = 8bit
   1bit就是一个1或0
   1KB = 1024byte
   1MB = 1024KB
   1GB = 1024MB
   1TB = 1024GB
   
   byte b = 2;  在计算机中是这样表示的:00000010
   short s = 2;  在计算机中是这样表示的:00000000 00000010
int i = 2;  在计算机中是这样表示的:00000000 00000000 00000000 00000010
  ...

类型 占用字节数量(byte)
--------------------------------
byte 1
   short 2
   int 4
   long 8
   float 4
   double 8
   boolean 1 (00000001)true, (00000000)false
   char 2

关于二进制?
二进制
1 2 3 4 5 6 7
      1 10 11 100 101 110 111...
十进制转换成二进制
125 转换成二进制
办法:除以2,然后余数逆序输出。
1111101
二进制转换成十进制
二进制1111011转换成十进制
如下图
   

 

 

 

 

 

 

1.4 byte类型的取值范围?

byte:[-128 ~ 127],可以标识256个不同的数字。
byte类型的最大值是怎么计算出来的呢?
byte是1个字节,是8个比特位,所以byte可以存储的最大值是:
01111111
注意:在计算机当中,一个二进制位最左边的是符号位,当为0时表示正数,当为1是表示负数,所以byte类型最大值是:01111111
01111111(二进制) = 10000000(二进制) - 1 = 127(十进制)
   
   有几个取值范围需要大家记住:
  byte: [-128 ~ 127]
  short: [-32768 ~ 32767]
  int: [-2147483648 ~ 2147483647]
  char: [0 ~ 65535]
  short和char实际上容量相同,不过char可以表示更大的数字,因为char表示的是文字,文字没有正负之分,所以char可以表示更大的数字

1.5 对于八种基本数据类型来说

其中byte, short, int, long, float, double, boolean,这7种数据类型计算机表示起来比较容易,因为他们都是数字。其中布尔类型只有两个值true和false,实际上true和false分别在c++中对应1和0,1为true,0为false。

对于char类型来说计算机表示起来比较麻烦,因为char对应的是文字,每一个国家的文字不一样,文字不能直接通过算法转换成二进制。这个时候怎么办?
字符编码诞生了。

什么是字符编码?
字符编码是人为的定义的一套转换表。
在字符编码中规定了一系列的文字对应的二进制。
字符编码其实本质上就是一本字典,该字典中描述了文字与二进制之间的对照关系。
字符编码是人为规定的。(是某个计算机协会规定的)

字符编码涉及到编码和解码两个过程,编码和解码的时候必须采用同一套字符编码方式,不然就会出现乱码。

关于字符编码的发展过程?
起初的时候计算机是不支持文字的,只支持科学计算。实际上计算机起初是为了战争而开发的,计算导弹的轨道...
   后来随着计算机的发展,计算机开始支持文字,最先支持的文字是英文,英文对应的字符编码方式是ASCII码。
   ASCII码采用1byte进制存储,因为英文字母是26个。(键盘上所有的键全部算上也超不过256个,1byte可以表示256种不同的情况。所以英文本身在计算机方面就占有优势)
  'a' --(采用ASCII码进行编码)--> 01100001
  01100001 --(采用ASCII码进行解码)--> 'a'
  如果编码和解码采用的不是同一个编码方式,会出现乱码。
  'A' ---> 65
  '0' ---> 48 (这个'0'不是那个0,是文字'0')
   随着计算机语言的发展,后来国际标准组织制定了ISO-8859-1编码方式,又称为latin-1编码方式,向上兼容ASCII码。但不支持中文。
   后来发展到亚洲,才支持中文,日文,韩文...
   中文这块的编码方式:GB2312 < GBK GB18030 (容量关系),这三种编码方式是简体中文。
   繁体中文:big5(台湾使用的是大五码)
   在java中,java语言为了支持全球所有文字,采用了一种字符编码方式叫做unicode编码。uninode编码统一了全球所有的文字,支持所有的文字。
   具体的实现包括:UTF-8/UTF-16/UTF-32
   需要记住:
  ASCII
  ISO-8859-1(latin-1
  GB2312
  GBK
  GB18030
  Big5
  unicode(utf8/utf16/utf32)
 

 

2 几种基本数据类型详解

2.1 字符型char

CharTest01.java

/*
字符型
char
1、char占用2个字节。
2、char的取值范围: [0 ~ 65535]
3、char类型的字面量使用单引号括起来。
4、char可以存储一个汉字。
*/

public class CharTest01{
public static void mian(String[] args){
// char可以存储一个汉字吗?
// 可以的,汉字占用2个字节,java中的char类型占用2个字节,正好
char c1 = '中';
char c2 = 'a';
// 0如果加上单引号的话,0就不是数字0了,就是文字0,它是1个字符。
char c3 = '0';
char c4 = '龘';

// 错误:不兼容的类型:String无法转换为char
// char c4 = "a";

// 错误:未结束的字符文字
// char c5 = 'ab';
}
}

CharTest02.java

/*
关于java中的转义字符
java语言中"\"负责转义。
\t 表示制表符tab
*/

public class CharTest02{
public static void main(String[] args){
// 普通't'字符
char c1 = 't';
System.out.println(c1);

// 根据之前所学,以下代码应该报销。
// 经过测试以下代码 \t 实际上是1个字符,不属于字符串
// 两个字符合在一起表示一个字符,其中 \t 表示“制表符tab”
char c2 = '\t';  // 相当于键盘上的“tab键”

System.out.println("abcdef");
System.out.println("abctdef");
// \的出现会将紧挨着的后面的字符进行转义。\碰到t表示“tab键”
System.out.println("abc\tdef");

/*
System.out.println(); 换行
System.out.print(); 不换行
*/
System.out.print("xiaohong");
System.out.println("HelloWorld");
System.out.print("abc");
System.out.println('\n');  // '\n'换行符
System.out.pirntln("def");

// 假设现在想在控制台输出一个 ' 字符怎么办?
// 错误:空字符文字
// System.out.println(''');
// \' 表示一个普通的单引号字符
System.out.println('\'');

// 假设现在想在控制台输出一个 \ 字符怎么办?
// 错误:未结束的字符文字
// System.out.println('\');
// 在java中两个反斜杠代表了一个“普通的反斜杠字符”
System.out.println('\\');

// 双引号的括起来的是字符串
System.out.println("test");
// 希望输出的结果是:"test"
// 错误:需要')'
// System.out.println(""test"");
System.out.println("“test”");  //内部的双引号可以用中文的。
System.out.println("\"test\"");

// 这个可以输出吗?
// 这个不需要专门进制转义
// 这个单引号在这里只是普通的字符,不具备特殊的含义
System.out.println("'");

// 编译报错,因为:4e2d是一个字符串
// 错误:未结束的字符文字
// char x = '4e2d';
// 反斜杠u表示后面的一个字符是unicode编码。
// unicode编码是十六进制的。
char x = '\u4e2d';
System.out.println(x);  // '中'

}
}

/*
十六进制,满16进1位:
1 2 3 4 5 6 7 8 9 a b c d e f 10
11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1f 20...

八进制:
0 1 2 3 4 5 6 7 8 10 11 12 13 14 15 16 17 20...
*/

 

 

 

2.2 整数型byte, short, int, long

IntTest01.java


/*
整数型在java语言中共4种类型:
byte 1个字节
short 2个字节
int   4个字节
long 8个字节

1个字节 = 8个二进制位
1byte = 8bit

对于以上的四个类型来说,最常用的是int。
开发的时候不用斤斤计较。直接选择使用int就行了。


在java语言中整数型字面量有4种表示形式:
十进制:最常用的。
二进制:
八进制:
十六进制:
*/

public class IntTest01{
public static void main(String[] args){

// 十进制
int a = 10;
System.out.println(a);  // 10

// 八进制
int b = 010;
System.out.println(b);  // 8

// 十六进制
int c = 0x10;
System.out.println(c);  // 16

// 二进制
int d = 0b10;
System.out.println(d);  // 2
}
}

IntTest02.java


/*
在java中有一条非常重要的结论,必须记住:
在任何情况下,整数型的“字面量”默认被当做int类型处理。
如果希望该“整数型字面量”被当做long类型来来处理,需要在“字面量”后面添加L/l,建议使用大写L,因为小写l和1不好分清
*/

public class IntTest02{
public static void main(String[] args){
// 分析这个代码存在类型转换吗,以下代码什么意思?
// 不存在类型转换
// 100 这个字面量被当做int类型处理
// a变量是int类型,所以不存在类型的转换。
// int类型的字面值赋值给int类型的变量。
int a = 100;
System.out.println(a);

// 分析这个程序是否存在类型转换?
// 分析:200这个字面是默认被当做int类型来处理
// b变量是long类型,int类型占4个字节,long类型占8个字节
// 小容量可以自动转换成大容量,这种操作被称为:自动类型转换。
long b = 200;
System.out.println(b);

// 分析这个是否存在类型转换?
// 这个不存在类型转换。
// 在整数型字面量300后面添加一个L之后,300L联合起来就是一个long类型的字面量
// c变量是long类型,long类型赋值给long类型不存在类型转换。
long c = 300L;
System.out.println(c);

// 题目:
// 可以吗?存在类型转换吗?
// 2147483647默认被当做int来处理
// d变量是long类型,小容量可以自动赋值给大容量,自动类型转换
lond d = 2147483647;

// 编译器会报错吗?为什么?
// 在java中整数型字面量一上来编译器就会将它看做int类型
// 而2147483648已经超出了int的范围,所以在没有赋值之前就出错了。
// 不是e放不下2147483648,e是long类型,完全可以容纳2147483648
// 错误:整数太大
// long e = 2147483648;
// 怎么解决这个问题?
long e = 2147483648L;
System.out.println(e);

}
}

IntTest03.java


/*
1、小容量可以直接赋值给大容量,称为自动类型转换。
2、大容量不能直接赋值给小容量,需要使用强制类型转换符进行强转。但需要注意的是:加强制类型转换符之后,虽然编译通过了,但是运行的时候可能会损失精度。
*/

public class IntTest03{
public static void main(String[] args){

// 不存在类型转换
// 100L是long类型字面量,x是long类型
long x = 100L;

// x是long类型,占用8个字节,而y变量是int类型,占用4个字节
// 在java语言中,大容量可以直接赋值给小容量吗?不允许
// 编译错误信息:错误:不兼容的类型:从long转换到int可能会有损失
// int y = x;

// 大容量转换成小容量,要想编译通过,必须加强制类型转换符,进行强制类型转换
// 底层是怎么进行强制类型转换的呢?
// long类型100L: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 01100100
// 以上的long类型的100L强转为int类型,会自动将“前面”的4个字节砍掉:00000000 00000000 00000000 01100100
int y = (int)x;  // 这个(int)就是强制类型转换符,加上去就能编译通过。,但是编译虽然通过了,但是运行时可能损失精度。
System.out.println(y);  // 100

// 定义变量a为int类型,赋值100
int a = 100;
int b = a;  // 将变量a中保存的值100复制一份给b变量
System.out.println(a);
System.out.println(b);

}
}

IntTest04.java


/*
java中有一个语法规则:
当这个整数型字面量没有超出byte的取值范围,那么这个整数型字面量可以直接赋值给byte类型的变量。

这种语法机制是为了方便编写代码右存在的。
*/

public class IntTest04{
public static void main(String[] args){
// 分析:以下代码编译可以通过吗?
// 300 被默认当做int类型
// b 变量是byte类型
// 大容量转换成小容量,要想编译通过,必须使用强制类型转换符
// 错误:不兼容的类型:从int转换到byte可能会出现损失
// byte b = 300;

// 要想让以上的程序编译通过,必须加强制类型转换符
// 虽然编译通过了,但是可能精度损失。
// 300这个int类型对应的二进制:00000000 00000000 00000001 00101100
// byte占用1个字节,砍掉前3个字节,结果是:00101100-->(44)
byte b = (byte)300;
System.out.print(b);  // 44

// 这个编译能通过吗?
// 1是int类型,默认被当做int类型来看。
// x是byte类型,1个字节,大容量无法直接转换成小容量。
// 按理说编译报错。
byte x = 1;  // 编译通过
byte x = 127;  // 编译通过

// 当整数型字面量没有超出short类型取值范围的时候,该字面量可以直接赋值给short类型的变量
short s = 1;
short s1 = 32767;
// 错误:不兼容的类型,从int类型转换到short可能会出现损失
// short s2 = 32768;
}
}
 

CharTest03.java

byte b = 127;  // 可以直接赋值
short s = 21767;  // 可以直接赋值
char // 没有超出char的取值范围可以直接赋值给char变量吗


/*
1、整数能否直接赋值给char
2、char x = 97;
这个java语句是允许的,并且输出的结果是'a'
经过这个测试得出两个结论:
结论1:当一个整数类型赋值给char类型变量的时候,会自动转换成char字符型,最终的结果是一个字符。
结论2:当一个整数没有超出byte, short, char的取值范围的时候,这个整数 可以直接赋值给byte, short, char类型的变量。

*/

public class CharTest03{
public static void main(String[] args){

char c1 = 'a';
System.out.println(c1);

// 这里会做类型转换吗?
// 97是int类型
// c2是char类型
char c2 = 97;
System.out.println(c2);

// char类型取值范围:[0 ~ 65535]
char c3 = 65535;  // 实际上最终是一个“看不懂”的字符。
System.out.println(c3);

// 错误:不兼容的类型:从int类型转换到char可能会有损失
// char c4 = 65536;
// System.out.println(c4);

// 怎么解决以上问题?
char c4 = (char)65536;
System.out.println(c4);
}
}

二进制码,原码、反码,补码

1、计算机在任何情况下都只能识别二进制

2、计算机在底层存储数据的时候,一律存储的是“二进制的补码形式”
计算机采用补码形式存储数据的原因是:补码形式效率最高。

3、什么是补码呢?
实际上是这样的,二进制有:原码,反码,补码

4、记住:
对于一个正整数来说:二进制原码,反码,补码是同一个,完全相同。
int i = 1;
对应的二进制的原码:00000000 00000000 00000000 00000001
对应的二进制的反码:00000000 00000000 00000000 00000001
对应的二进制的补码:00000000 00000000 00000000 00000001
对于一个负数来说:二进制原码,反码,补码是什么关系呢?
byte i = -1;
对应的二进制原码:10000001
对应的二进制反码(符号位不变,其它位取反):11111110
对应的二进制补码(反码 + 1):11111111

5、分析 byte b = (byte)150;
这个b是多少?
int类型的4个字节的150的二进制码是什么?
00000000 00000000 00000000 10010110
将以上的int类型强制类型转为1个字节的byte,最终在计算机中的二进制码是
10010110
千万要注意:计算机永远存储的都是二进制补码形式。也就是说上面
10010110 这个是一个二进制补码形式,你可以采用逆推导的方式推算出这个二进制补码对应的原码是什么?
10010110 --> 二进制补码形式
10010101 --> 二进制反码形式
11101010 --> 二进制原码形式


public class IntTest05{
public static void main(String[] args){
// 编译报错:因为150已经超出了byte取值范围,不能直接赋值,需要强转
// byte b = 150;
// System.out.println(b);

byte b = (byte)150;
// 这个结果会输出多少呢?
System.out.println(b);  // -106
}
}

byte, short , char的混合运算


/*
结论:byte、char、short做混合运算的时候,各自先转换成int再做混合运算。
*/


public class IntTest06{
public static void main(String[] args){
char c1 = 'a';
byte b = 1;
// 注意:这里的加号是负责求和的
System.out.println(c1 + b);

// 错误:不兼容的类型:从int转换到short可能会有损失
// short s = c1 + b; // 编译器不知道这个加法最后的结果是多少,只知道是int类型

// 这样修改行吗?
// 错误:不兼容的类型:从int转换到short可能会有损失
// short s = (short)c1 + b;

short s = (short)(c1 + b);

int a = 1;
// 错误:不兼容的类型:从int转换到short可能会有损失
// short x = 1; // 可以
// short x = a; // 不可以,编译器只知道a是int类型,不知道a中存储的是哪个值
// System.out.println(x);

short f = 97 + 1;  // 可以
short k = 98;  // 可以
}
}

多种数据类型混合运算


/*
结论:多种数据类型做混合运算的时候,最终的结果是“最大容量”对应的类型。

char + short + byte 这个除外。因为这三个做混合运算的时候,会各自先转换成int再做混合运算。
*/

public class IntTest07{
public static void main(String[] args){
long a = 10L;
char c = 'a';
short s = 100;
int i = 30;
System.out.println(a + c + s + i);  // 237

// 错误:不兼容的类型:从long转换到int可能会有损失
// 计算结果是long类型
// int x = a + c + s + i;
int x = long(a + c + s + i);
System.out.println(x);

// 以下程序执行的结果是?
// java中规定,int类型和int类型最终的结果还是int类型。
int temp = 10 / 3;  // / 是除号。 (最终取整)
System.out.println(temp);  // 结果是:3

// 在java中计算结果不一定是精确的
int temp2 = 1 / 2;
System.out.println(temp2);
}
}

2.3 浮点型

关于java语言中的浮点型数据
浮点型包括:
float 4个字节
double      8个字节

float是单精度
double是双精度
double更精确

比如说:
10.0 / 3.0 如果采用float来存储的话结果可能是:3.3333333
10.0 / 3.0 如果采用double来存储的话结果可能是:3.3333333333333335

但是需要注意的是,如果用在银行方面或者说使用在财务方面,double也是远远不够的,在java中提供了一种精度更高的类型,这种类型专门使用在财务软件方面:java.math.BigDecimal

float和double存储数据的时候都是存储的近似值。为什么?
因为现实世界中有这种无限循环的数据,例如:3.3333333333...
数据实际上是无限循环,但是计算机的内存有限,用一个有限的资源表示无限的数据,只能存储近似值。

long类型占用8个字节。
float类型占用4个字节。
哪个容量大?
注意:任意一个浮点型都比整数型空间大
float容量 > long容量

java中规定,任何一个浮点型数据默念被当做double来处理。如果想让这个浮点型字面量被当做float类型来处理,那么需要在字面量后面添加F/f。
1.0 默念被当做double类型处理。
1.0F 这才是float类型。


public class FloatTest01{
public static void main(String[] args){
System.out.println(10.0 / 3.0);
System.out.println(10.0F / 3.0F);

// 这个不存在类型转换
// 3.14159是double类型
// pi是double类型
double pi = 3.14159

// 这个可以吗?
// 错误:不兼容的类型:从double转换到float可能会有损失
// float f = 3.14;

// 怎么修改以上的代码呢?
// 方式1
// float f = 3.14f;
// 方式2:强制类型转换,但可能损失精度,谨慎使用
float f = float(3.14);

// 分析这个程序可以编译通过吗?
// 错误:不兼容的类型:从double转换到int可能会有损失
// 原理:先将5转换成double类型,然后再做运算,结果是double
// 大容量无法直接赋值给小容量,需要强制。
// int i = 10.0 / 5;

// 怎么修改
int i = (int)10.0 / 5;

// 可以这样修改吗?可以
int i = (int)(10.0 / 5);
}
}

2.4 布尔类型boolean


/*
1、在java语言中boolean类型只有两个值,没有其他值:
true和false
不像c或者c++,以语言中1和0也可以表示布尔类型。

2、boolean类型在实际开发中使用在哪里呢?
使用在逻辑判断当中,通常放到条件的位置上(充当条件)
*/

public class BooleanTest01{
public static void main(){

// 错误:不兼容的类型:int无法转换为boolean
// boolean sex = 1;

boolean sex = true;

// 后面我们会学习if语句
// if语句是一个条件语句
// 可以实现什么功能呢?例如:如果A账户的钱充足,才可以向B账户转账。
// 例如:如果这个布尔型值是真true,则表示男性,为false则表示女性。

if(sex){
System.out.println('男');
}else{
System.out.println('女');
}

int a = 10;
int b = 20;
System.out.println(a < b);
System.out.println(a > b);
}
}

2.5 基本数据类型转换规则

1.八种基本数据类型中,除boolean类型不能转换,剩下的七种类型之间都可以进制转换。

2.如果整数型字面量没有超出byte, short, char的取值范围,可以直接将其赋值给byte, short, char类型的变量。

3.小容量向大容量转换称为自动类型转换,容量从小到大的排序为:byte < short(char) < int < long < float < double, 其中short和char都占用两个字节,但是char可以表示更大的正整数。

4.大容量转换成小容量,称为强制类型转换,编写时必须添加“强制类型转换符”,但运行时可能出现精度损失,谨慎使用。

5.byte, short, char类型混合运算时,先各自转换成int类型再做运算。

6.多种数据类型混合运算,各自先转换成容量最大的那一种再做运算。


public class TypeTransferTest{
public static void main (string[] args){
// 编译报错,因为1000已经超出byte取值范围
byte b1 = 1000 ;

// 可以
byte b2 = 20;

// 可以
short s = 1000;

// 可以
int c = 1000;

// 可以
long d = c;

// 编译报错
int e = d;

// 可以
int f = 10 / 3;

// 可以
long g = 10;

// 编译报错
int h = g / 3 ;

// 可以
long m = g / 3 ;

// 编译报错
byte x = (byte)g / 3;

// 可以
short y = (short)(g / 3);

// 可以
short i = 10;

// 可以
byte j = 5;

// 编译报错
short k = i +j;

// 可以
int n = i + j;

// 可以
char cc = 'a' ;
System.out.println(cc);  // a
System.out.println((byte)cc);  // 97

// cc会先自动转换成int类型,再做运算
int o = cc + 100 ;
System.out.println (o) ;
}
}

 

 

 
 

 

posted @   路走  阅读(132)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示