变量是申请内存来存储值。也就是说,当创建变量的时候,需要在内存中申请空间 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据

image.png
因此,通过定义不同类型的变量,可以在内存中储存整数、小数或者字符。Java 的两大数据类型:

  • 内置数据类型 (基本数据类型)
  • 引用数据类型

数据类型

基本类型

四类 八种 大小 数据表示范围
布尔型 boolean 1 字节 只有两个取值:true 和 false true
boolean数据类型表示一位的信息
例子:boolean one = true
字符型 char 2 字节 \u0000 ~ \uffff 默认值 \u0000
0 ~ 65,535
char类型是一个单一的 16 位 Unicode 字符
char 数据类型可以储存任何字符
例子:char letter = ‘A’ (“a”, “A”, “0”,”家”)
整型 byte 1 字节 -2^7 ~ 2^7-1 默认值 0
-128 ~ 127
byte 数据类型是8位、有符号的,以二进制补码表示的整数
byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一
例子:byte a = 100,byte b = -50
short 2 字节 -2^15 ~ 2^15 - 1 默认值 0
-32768 ~ 32767
short 数据类型是 16 位、有符号的以二进制补码表示的整数
Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一
例子:short s = 1000,short r = -20000
int 4 字节 -2^31 ~ 2^31 - 1 默认值 0
-2,147,483,648 ~ 2,147,483,647
一般地整型变量默认为 int 类型
int 数据类型是32位、有符号的以二进制补码表示的整数
例子:int a = 100000, int b = -200000
long 8 字节 -2^63 ~ 2^63 - 1 默认值 0L
-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
long 数据类型是 64 位、有符号的以二进制补码表示的整数
这种类型主要使用在需要比较大整数的系统上
“L”理论上不分大小写,但是若写成”l”容易与数字”1”混淆,不容易分辩。所以最好大写
例子: long a = 100000L,Long b = -200000L
浮点型 float 4 字节 -2^128 ~ +2^128 默认值 0.0f
-3.403E+38 ~ +3.403E+38
float 数据类型是单精度、32位、符合IEEE 754标准的浮点数
float 在储存大型浮点数组的时候可节省内存空间
浮点数不能用来表示精确的值,如货币
例子:float f1 = 234.5f
double 8 字节 -2^1024 ~ +2^1024 默认值 0.0f
-1.79E+308 ~ +1.79E+308
- [x] 一般地浮点型变量默认为 double 类型

double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数
浮点数的默认类型为double类型
例子:double d1 = 123.4 | |
- 数据范围与字节无关,例如float数据范围比long更加广泛,而float是4字节,long是8字节
- 如果是整型,默认为int,如果是浮点型,默认double,
- 如果要使用long或float类型,需要加上后缀,例如100L,100.0F
- 字符串不是基本类型,而是引用类型
- 浮点型可能只是一个近似值,并非精确值
| | | |

  1. public class PrimitiveTypeTest {
  2. public static void main(String[] args) {
  3. // char
  4. System.out.println("基本类型:char 二进制位数:" + Character.SIZE);
  5. System.out.println("包装类:java.lang.Character");
  6. // 以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台
  7. System.out.println("最小值:Character.MIN_VALUE=" + (int) Character.MIN_VALUE);
  8. // 以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台
  9. System.out.println("最大值:Character.MAX_VALUE=" + (int) Character.MAX_VALUE);
  10. System.out.println();
  11. // byte
  12. System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE);
  13. System.out.println("包装类:java.lang.Byte");
  14. System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE);
  15. System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE);
  16. System.out.println();
  17. // short
  18. System.out.println("基本类型:short 二进制位数:" + Short.SIZE);
  19. System.out.println("包装类:java.lang.Short");
  20. System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE);
  21. System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE);
  22. System.out.println();
  23. // int
  24. System.out.println("基本类型:int 二进制位数:" + Integer.SIZE);
  25. System.out.println("包装类:java.lang.Integer");
  26. System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE);
  27. System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE);
  28. System.out.println();
  29. // long
  30. System.out.println("基本类型:long 二进制位数:" + Long.SIZE);
  31. System.out.println("包装类:java.lang.Long");
  32. System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE);
  33. System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE);
  34. System.out.println();
  35. // float
  36. System.out.println("基本类型:float 二进制位数:" + Float.SIZE);
  37. System.out.println("包装类:java.lang.Float");
  38. System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE);
  39. System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE);
  40. System.out.println();
  41. // double
  42. System.out.println("基本类型:double 二进制位数:" + Double.SIZE);
  43. System.out.println("包装类:java.lang.Double");
  44. System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE);
  45. System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE);
  46. System.out.println();
  47. }
  48. }

编译以上代码输出结果如下所示:运行实例 »

基本类型:char 二进制位数:16
包装类:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535

基本类型:byte 二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127

基本类型:short 二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE=-32768
最大值:Short.MAX_VALUE=32767

基本类型:int 二进制位数:32
包装类:java.lang.Integer
最小值:Integer.MIN_VALUE=-2147483648
最大值:Integer.MAX_VALUE=2147483647

基本类型:long 二进制位数:64
包装类:java.lang.Long
最小值:Long.MIN_VALUE=-9223372036854775808
最大值:Long.MAX_VALUE=9223372036854775807

基本类型:float 二进制位数:32
包装类:java.lang.Float
最小值:Float.MIN_VALUE=1.4E-45
最大值:Float.MAX_VALUE=3.4028235E38

基本类型:double 二进制位数:64
包装类:java.lang.Double
最小值:Double.MIN_VALUE=4.9E-324
最大值:Double.MAX_VALUE=1.7976931348623157E308

float和double的最小值和最大值都是以科学记数法的形式输出的,结尾的”E+数字”表示E之前的数字要乘以10的多少次方。比如3.14E3就是3.14 × 103 =3140,3.14E-3 就是 3.14 x 10-3 =0.00314
实际上,JAVA中还存在另外一种基本类型 void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作

引用类型

  • 在Java中,引用类型的变量非常类似于C/C++的指针。引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定为一个特定的类型,比如 Employee、Puppy 等。变量一旦声明后,类型就不能被改变了
  • 对象 数组 类 字符串 接口 Lambda 都是引用数据类型
  • 所有引用类型的默认值都是null
  • 一个引用变量可以用来引用任何与之兼容的类型
  • 例子:Site site = new Site(“Runoob”)

类型默认值

下表列出了 Java 各个类型的默认值:

数据类型 默认值
boolean false
char ‘u0000’
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
String (or any object) null
public class Test {
    static boolean bool;
    static char ch;
    static byte by;
    static double d;
    static float f;
    static int i;
    static long l;
    static short sh;
    static String str;

    public static void main(String[] args) {
        System.out.println("Bool :" + bool);
        System.out.println("Character:" + ch);
        System.out.println("Byte :" + by);
        System.out.println("Double :" + d);
        System.out.println("Float :" + f);
        System.out.println("Integer :" + i);
        System.out.println("Long :" + l);
        System.out.println("Short :" + sh);
        System.out.println("String :" + str);
    }
}

/*
Bool :false
Character:
Byte :0
Double :0.0
Float :0.0
Integer :0
Long :0
Short :0
String :null
*/

Java 常量

常量在程序运行时是不能被修改的
在 Java 中使用 final 关键字来修饰常量,声明方式和变量类似:

final double PI = 3.1415927;

虽然常量名也可以用小写,但为了便于识别,通常使用大写字母表示常量。
字面量可以赋给任何内置类型的变量。例如:

byte a = 68;
char a = 'A'

byte、int、long、和short都可以用十进制、16进制以及8进制的方式来表示。
当使用常量的时候,前缀 0 表示 8 进制,而前缀 0x 代表 16 进制, 例如:

int decimal = 100;
int octal = 0144;
int hexa =  0x64;

和其他语言一样,Java的字符串常量也是包含在两个引号之间的字符序列。下面是字符串型字面量的例子:

"Hello World"
"two\nlines"
"\"This is in quotes\""

字符串常量和字符常量都可以包含任何Unicode字符。例如:

char a = '\u0001';
String a = "\u0001";

Java语言支持一些特殊的转义字符序列

符号 字符含义
\n 换行 (0x0a)
\r 回车 (0x0d)
\f 换页符(0x0c)
\b 退格 (0x08)
\0 空字符 (0x0)
\s 空格 (0x20)
\t 制表符
\“ 双引号
\‘ 单引号
\\ 反斜杠
\ddd 八进制字符 (ddd)
\uxxxx 16进制Unicode字符 (xxxx)

自动类型转换

整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算

转换从低级到高级

低---------------------------> 高
byte,short,char—> int —> long—> float —> double

数据类型转换必须满足如下规则:

    1. 不能对boolean类型进行类型转换
    1. 不能把对象类型转换成不相关类的对象
    1. 在把容量大的类型转换为容量小的类型时必须使用强制类型转换
    1. 转换过程中可能导致溢出或损失精度,例如: ```java int i =128;
      byte b = (byte)i;

因为 byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出


- 5. 浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入,例如:
```java
(int)23.7 == 23;        
(int)-45.89f == -45

自动类型转换

必须满足转换前的数据类型的位数要低于转换后的数据类型,例如: short数据类型的位数为16位,就可以自动转换位数为32的int类型,同样float数据类型的位数为32,可以自动转换为64位的double类型

public class ZiDongLeiZhuan{
        public static void main(String[] args){
            char c1='a';//定义一个char类型
            int i1 = c1;//char自动类型转换为int
            System.out.println("char自动类型转换为int后的值等于"+i1);
            char c2 = 'A';//定义一个char类型
            int i2 = c2+1;//char 类型和 int 类型计算
            System.out.println("char类型和int计算后的值等于"+i2);
        }
}

解析:c1 的值为字符 a ,查 ASCII 码表可知对应的 int 类型值为 97, A 对应值为 65,所以 i2=65+1=66

image.png

强制类型转换

  • 条件是转换的数据类型必须是兼容的
  • (type)value 是要强制类型转换后的数据类型 ```java public class QiangZhiZhuanHuan { public static void main(String[] args) { int i1 = 123; byte b = (byte) i1;// 强制类型转换为byte System.out.println(“int强制类型转换为byte后的值等于” + b);

    short s = 20; // s = s + 10; //❌ Type mismatch: cannot convert from int to shortType mismatch: // cannot convert from int to short s = (short) (s + 10); // ✅ } }

/ 运行结果 int强制类型转换为byte后的值等于123 /

![东方姑娘.png](https://cdn.nlark.com/yuque/0/2020/png/604921/1597799818145-0943713e-45e7-4ce8-9d2c-3d1942fa780a.png#height=260&id=h3gaK&name=%E4%B8%9C%E6%96%B9%E5%A7%91%E5%A8%98.png&originHeight=260&originWidth=743&originalType=binary&ratio=1&size=27284&status=done&style=none&width=743)

- 强制类型转换一般不推荐使用,因为有可能发生精度损失、数据溢出
- byte/short/char这三种类型都可以发生数学运算,例如加法“+”
- byte/short/char这三种类型在运算的时候,都会被首先**类型提升**成为int类型,然后再计算
- boolean类型不能发生数据类型转换


<a name="lunEI"></a>
#### 隐含强制类型转换

- 1. 整数的默认类型是 int
- 2. 浮点型不存在这种情况,因为在定义 float 类型时必须在数字后面跟上 F 或者 f


<a name="tbmUR"></a>
#### 编译器器的补充与优化

- 变量进行赋值的时候,如果右侧的表达式中全都是常量,那么编译器javac将会直接将若干个常量表达式计算得到结果
- short result = 5 + 8; // 等号右边全都是常量,没有任何变量参与运算,编译之后,得到的.class字节码文件当中相当于【直接就是: short result = 13;】, 这称为“编译器的常量优化”,但是注意:一旦表达式当中有变量参与,那么就不能进行这种优化了
```java
// short + short --> int + int --> int
short result = 5 + 8; 

//变量相加
short a = 5;
short b = 8;
// short result = a + b; // 错误写法!左侧需要是int类型
// short result2 = 5 + a + 8; // 18,报错
  • 对于byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围,那么javac编译器将会自动隐含地为我们补上一个(byte)(short)(char) ```java public static void main(String[] args) { byte num1 = /(byte)/ 30; // 右侧没有超过左侧的范围 不是自动类型转换 System.out.println(num1); // 30
// byte num2 = 128; // 右侧超过了左侧的范围 ,报错


// int --> char,没有超过范围 编译器将会自动补上一个隐含的(char)
char zifu = /*(char)*/ 65;
System.out.println(zifu); // A

}


<a name="CghhW"></a>
### ASCII编码表
编码表就是将人类的文字和一个十进制数进行对应起来组成一张表<br />ASCII码表 American Standard Code for Information Interchange,美国信息交换标准代码<br />Unicode码表 万国码。也是数字和符号的对照关系,开头0-127部分和ASCII完全一样,但是从128开始包含有更多字符<br />![受到日方提供好.png](https://cdn.nlark.com/yuque/0/2020/png/604921/1597800567566-a52d2777-198b-4e3f-836c-0b169db700bd.png#height=713&id=qSicA&name=%E5%8F%97%E5%88%B0%E6%97%A5%E6%96%B9%E6%8F%90%E4%BE%9B%E5%A5%BD.png&originHeight=713&originWidth=667&originalType=binary&ratio=1&size=117292&status=done&style=shadow&width=667)
```java
public class Demo03DataTypeChar {
    public static void main(String[] args) {
        char zifu1 = '1';
        char zifu2 = 'A'; // 其实底层保存的是65数字
        char zifu3 = 'c';

        System.out.println(zifu1 + 0); // 49

        // 左侧是int类型,右边是char类型,
        // char --> int,确实是从小到大
        // 发生了自动类型转换
        int num = zifu3;
        System.out.println(num); // 99

        char zifu4 = '中'; // 正确写法
        System.out.println(zifu4 + 0); // 20013
    }
}

Java 格式化输出 printf 例子

java格式化输出.png

d 十进制数
%06d:表示显示6位数,不够长度前面用0补齐
o 八进制数
x 十六进制数
f 浮点数
%0.2f:表示小数点后只显示两位小数
s 字符串
c 字符
b 布尔值
h 散列值
n 和平台有关的行分隔符

java格式化输出2.png

+ 打印正负号
- 左对齐
, 千位分隔符
8.2f 8表示字符宽度,2表示小数点位数
空格 添加空格
import java.util.Date;

/**
 * 使用printf输出
 */
/**
 * 关键技术点 使用java.io.PrintStream的printf方法实现C风格的输出 printf
 * 方法的第一个参数为输出的格式,第二个参数是可变长的,表示待输出的数据对象
 */
public class Printf {

    public static void main(String[] args) {
        /*** 输出字符串 ***/
        // %s表示输出字符串,也就是将后面的字符串替换模式中的%s
        System.out.printf("%s", new Integer(1212));
        // %n表示换行
        System.out.printf("%s%n", "end line");
        // 还可以支持多个参数
        System.out.printf("%s = %s%n", "Name", "Zhangsan");
        // %S将字符串以大写形式输出
        System.out.printf("%S = %s%n", "Name", "Zhangsan");
        // 支持多个参数时,可以在%s之间插入变量编号,1$表示第一个字符串,3$表示第3个字符串
        System.out.printf("%1$s = %3$s %2$s%n", "Name", "san", "Zhang");

        /*** 输出boolean类型 ***/
        System.out.printf("true = %b; false = ", true);
        System.out.printf("%b%n", false);

        /*** 输出整数类型 ***/
        Integer iObj = 342;
        // %d表示将整数格式化为10进制整数
        System.out.printf("%d; %d; %d%n", -500, 2343L, iObj);
        // %o表示将整数格式化为8进制整数
        System.out.printf("%o; %o; %o%n", -500, 2343L, iObj);
        // %x表示将整数格式化为16进制整数
        System.out.printf("%x; %x; %x%n", -500, 2343L, iObj);
        // %X表示将整数格式化为16进制整数,并且字母变成大写形式
        System.out.printf("%X; %X; %X%n", -500, 2343L, iObj);

        /*** 输出浮点类型 ***/
        Double dObj = 45.6d;
        // %e表示以科学技术法输出浮点数
        System.out.printf("%e; %e; %e%n", -756.403f, 7464.232641d, dObj);
        // %E表示以科学技术法输出浮点数,并且为大写形式
        System.out.printf("%E; %E; %E%n", -756.403f, 7464.232641d, dObj);
        // %f表示以十进制格式化输出浮点数
        System.out.printf("%f; %f; %f%n", -756.403f, 7464.232641d, dObj);
        // 还可以限制小数点后的位数
        System.out.printf("%.1f; %.3f; %f%n", -756.403f, 7464.232641d, dObj);

        /*** 输出日期类型 ***/
        // %t表示格式化日期时间类型,%T是时间日期的大写形式,在%t之后用特定的字母表示不同的输出格式
        Date date = new Date();
        long dataL = date.getTime();
        // 格式化年月日
        // %t之后用y表示输出日期的年份(2位数的年,如99)
        // %t之后用m表示输出日期的月份,%t之后用d表示输出日期的日号
        System.out.printf("%1$ty-%1$tm-%1$td; %2$ty-%2$tm-%2$td%n", date, dataL);
        // %t之后用Y表示输出日期的年份(4位数的年),
        // %t之后用B表示输出日期的月份的完整名, %t之后用b表示输出日期的月份的简称
        System.out.printf("%1$tY-%1$tB-%1$td; %2$tY-%2$tb-%2$td%n", date, dataL);

        // 以下是常见的日期组合
        // %t之后用D表示以 "%tm/%td/%ty"格式化日期
        System.out.printf("%1$tD%n", date);
        // %t之后用F表示以"%tY-%tm-%td"格式化日期
        System.out.printf("%1$tF%n", date);

        /*** 输出时间类型 ***/
        // 输出时分秒
        // %t之后用H表示输出时间的时(24进制),%t之后用I表示输出时间的时(12进制),
        // %t之后用M表示输出时间的分,%t之后用S表示输出时间的秒
        System.out.printf("%1$tH:%1$tM:%1$tS; %2$tI:%2$tM:%2$tS%n", date, dataL);
        // %t之后用L表示输出时间的秒中的毫秒
        System.out.printf("%1$tH:%1$tM:%1$tS %1$tL%n", date);
        // %t之后p表示输出时间的上午或下午信息
        System.out.printf("%1$tH:%1$tM:%1$tS %1$tL %1$tp%n", date);

        // 以下是常见的时间组合
        // %t之后用R表示以"%tH:%tM"格式化时间
        System.out.printf("%1$tR%n", date);
        // %t之后用T表示以"%tH:%tM:%tS"格式化时间
        System.out.printf("%1$tT%n", date);
        // %t之后用r表示以"%tI:%tM:%tS %Tp"格式化时间
        System.out.printf("%1$tr%n", date);

        /*** 输出星期 ***/
        // %t之后用A表示得到星期几的全称
        System.out.printf("%1$tF %1$tA%n", date);
        // %t之后用a表示得到星期几的简称
        System.out.printf("%1$tF %1$ta%n", date);

        // 输出时间日期的完整信息
        System.out.printf("%1$tc%n", date);
    }
}
/**
 * printf方法中,格式为"%s"表示以字符串的形式输出第二个可变长参数的第一个参数值;
 * 格式为"%n"表示换行;格式为"%S"表示将字符串以大写形式输出;在"%s"之间用"n$"表示
 * 输出可变长参数的第n个参数值.格式为"%b"表示以布尔值的形式输出第二个可变长参数 的第一个参数值.
 */
/**
 * 格式为"%d"表示以十进制整数形式输出;"%o"表示以八进制形式输出;"%x"表示以十六进制
 * 输出;"%X"表示以十六进制输出,并且将字母(A、B、C、D、E、F)换成大写.格式为"%e"表
 * 以科学计数法输出浮点数;格式为"%E"表示以科学计数法输出浮点数,而且将e大写;格式为
 * "%f"表示以十进制浮点数输出,在"%f"之间加上".n"表示输出时保留小数点后面n位.
 */
/**
 * 格式为"%t"表示输出时间日期类型."%t"之后用y表示输出日期的二位数的年份(如99)、用m
 * 表示输出日期的月份,用d表示输出日期的日号;"%t"之后用Y表示输出日期的四位数的年份
 * (如1999)、用B表示输出日期的月份的完整名,用b表示输出日期的月份的简称."%t"之后用D
 * 表示以"%tm/%td/%ty"的格式输出日期、用F表示以"%tY-%tm-%td"的格式输出日期.
 */
/**
 * "%t"之后用H表示输出时间的时(24进制),用I表示输出时间的时(12进制),用M表示输出时间
 * 分,用S表示输出时间的秒,用L表示输出时间的秒中的毫秒数、用 p 表示输出时间的是上午还是
 * 下午."%t"之后用R表示以"%tH:%tM"的格式输出时间、用T表示以"%tH:%tM:%tS"的格式输出 时间、用r表示以"%tI:%tM:%tS
 * %Tp"的格式输出时间.
 */
/**
 * "%t"之后用A表示输出日期的全称,用a表示输出日期的星期简称.
 */