Java变量和数据类型

image

1. 注释

1.1 注释介绍

1.1.1 注释是什么

注释(Comment)就是程序的说明书,用于在Java源文件指定位置添加的说明性信息(对代码的一种解释)。

通常情况下开发人员在编写代码的时候,如果想要实现的功能比较复杂(实现功能的代码量有几十行甚至几百行),此时就需要在程序中添加适当的注释,其好处就是方便程序后期的维护以及增强程序的可读性软件开发是团队协作(多人共同开发一个项目),希望大家从现在开始养成良好的开发习惯:在代码中添加适当的注释。

1.1.2 Java注释的分类

在Java程序中能够使用的注释有三种,不同的注释在使用时位置不同。

  1. 单行注释: 使用//表示,只能注释一行,在方法的代码上使用

  2. 多行注释:使用/**/表示,可以注释多行,在方法中的代码上使用

  3. 文档注释:使用/***/表示,可以注释多行,JDK提供的开发工具javadoc提取类中文档注释的内容生成以网页文件形式体现的Java API文档,文档注释可以用在类上、接口上、枚举上、注解上,除此以外还有类中的成员变量上成员方法上构造器上代码块上,文档注释是日常开发中使用最多的注释。

1.1.3 Java注释的作用

  1. 对程序中的代码进行解释说明

  2. 在开发项目时可以先将自己的思路和实现步骤通过注释整理出来,再用代码去实现

  3. 在调试项目时可以注释部分可能错误的代码再对程序进行调试

1.2 Java注释的使用

  1. 新建包

选中java-core模块的src目录,然后右键New Package

image

输入net.ittimeline.java.core.foundational.syntax包名后回车

image

syntax包创建成功

image

  1. 新建类

选择net.ittimeline.java.core.foundational,然后右键 New>Java Class

image

设置类名为Comments 并回车

image

然后设置类的描述后点击OK

image

  1. 编写代码

此时代码中没有单行注释和多行注释,只有Comments类上有文档注释

 package net.ittimeline.java.core.foundational.syntax;
    
    /**
     * Java三种注释的使用
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/7 8:37
     * @since Java17
     */
    public class Comments {
        public static void main(String[] args) {
            System.out.println("Java三种注释的使用");
        }
    }
  1. 运行程序

在编辑区右键Run运行程序

image

程序的运行结果 打印输出Java三种注释的使用并换行

image

  1. 添加三种注释
 package net.ittimeline.java.core.foundational.syntax;
    //文档注释的使用
    /**
     * Java三种注释的使用
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/7 8:37
     * @since Java17
     */
    public class Comments {
        //文档注释的使用
        /**
         * main方法是Java程序的入口
         * 程序是从main方法的第一行非注释的代码开始执行
         * @param args 命令行输入的参数
         */
        public static void main(String[] args) {
            //单行注释的使用
            //往终端打印输出Java三种注释的使用并换行
            System.out.println("Java三种注释的使用");
            //多行注释的使用
            /*
                Java程序的开发步骤
                1. New Package
                2. New Java Class
                3. Write Java Code
                4. Run/Debug Program
             */
        }
    }
  1. 再次运行程序

image

程序的运行结果还是打印输出Java三种注释的使用并换行,同时对比未添加注释之前,增强了程序的可维护性。

image

1.3 Java注释使用注意事项

  1. 多行注释在使用的时候不要嵌套使用,否则会出现编译错误

Java编译器会根据就近原则查找/*最近的*/

image

  1. 注释的内容不会参与编译,编译后的字节码文件中不会包含注释的内容,添加注释不会影响程序的执行结果。

image

1.4 Java注释在API中的使用

目前只需要能够分辨出Java API中的注释即可不需要读懂Java API的源码

Java17提供了非常多供日常开发使用的API,在java项目的External Libraries的Java17的java.base模块下可以找到这些API

image

我们以java.lang包中的String为例

image

当我们打开String.java后,默认是Reader Mode

image

点击Reader Mode左边的x退出阅读模式

image

然后就能看到Java三种注释的各种应用

方法中的单行注释

image

方法中的多行注释

image

成员变量的文档注释

image

构造方法的文档注释

image

成员方法的文档注释

image

2. 字面量

2.1 字面量介绍

程序是来源于生活的,那么如何在程序中表示日常生活中常见的数据,例如身高180.0,体重140,姓名小明等等

字面量(Literal)指的是程序中直接写出来的数据,不同类型的字面量在程序中的书写格式也是不同的,例如140表示整数字面量,180.0表示小数字面量,"跟光磊学Java从小白到架构师"表示字符串字面量

在Java语言中包含六种类型的字面量

字面量类型说明案例
整数类型不带小数点的数字100,88,-66
小数类型带小数点的数字3.14,-5.12
字符串类型用双引号括起来的内容,内容可以有0到多个“HelloWorld”,“跟光磊学Java从小白到架构师” ,“”," "
字符字类型用单引号括起来的内容,内容只有一个‘a’,‘A’,‘我’
布尔字类型布尔值,表示真假取值只能是true或者false
空类型一个特殊的值,空值值是null

2.2 Java字面量使用

Literal.java演示6种字面量在Java程序中的使用:使用System.out.println()打印语句打印输出6种字面量的值

 package net.ittimeline.java.core.foundational.syntax.literal;
    
    /**
     * Java六种字面量的使用
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/7 14:55
     * @since Java17
     */
    public class Literal {
        public static void main(String[] args) {
            //打印输出6种字面量
            
            //整数字面量的使用
            System.out.println(100);
            System.out.println(200);
            System.out.println(-100);
    
            //小数字面量的使用
            System.out.println(3.14);
            System.out.println(13.14);
            System.out.println(-5.12);
    
            //字符串字面量的使用
            System.out.println("Hello World");
            System.out.println("光磊");
            System.out.println("跟光磊学Java从小白到架构师");
            //空字符串
            System.out.println("");
            //空格
            System.out.println(" ");
    
            //字符字面量的使用
            System.out.println('男');
            System.out.println('女');
            System.out.println('a');
            System.out.println('中');
    
            //布尔字面量的使用
            //布尔类型字面量取值只能是true或者false
            System.out.println(true);
            System.out.println(false);
    
            //空字面量的使用
            //null不能直接打印输出,否则程序运行报错:对println的引用不明确
            //System.out.println(null);
            //如果要打印null,那么只能用字符串的形式打印
            System.out.println("null");
    
        }
    }

程序运行结果

image

需求:打印输出个人信息,包括姓名、性别、工作所在地

PersonalInfo.java用于打印输出个人信息

package net.ittimeline.java.core.foundational.syntax;

/**

  • 案例:打印输出个人信息,包括姓名、性别、工作所在地
  • @author tony 18601767221@163.com
  • @version 2023/7/7 15:19
  • @since Java17
    */
    public class PersonalInfo {
    public static void main(String[] args) {
    System.out.println(“姓名:刘光磊”);
    System.out.println(“性别:男”);
    System.out.println(“工作所在地:上海”);
    }
    }

程序运行结果

image

3. 变量

3.1 变量概述

3.1.1 什么是变量

程序是由指令和数据组成的,程序是在内存中运行的,如何操作内存中的数据?

一花一世界,如果把一个程序看作一个世界或一个社会的话,那么变量就是程序世界的花花草草、万事万物。即变量是程序中不可或缺的组成单位,最基本的存储单元

我们以手机为例,手机的型号、价格、品牌、颜色等等信息都是变量

image

变量就是在程序执行的过程中,其值有可能发生改变的量

变量的作用就是用来操作内存中的数据(存储数据、修改数据)

变量的本质就是一块可以操作的内存空间,内存空间的位置是确定的,但是内存空间具体存储的内容(数据)是不确定的,也就是说内存空间具体存储的内容(数据)是可以在同一类型范围内发生改变的。

3.1.2 变量三要素

变量包含数据类型变量名变量值(数据值)三个要素

假如国庆节你想要去北京旅游,旅游就需要提前订好酒店

酒店是有多种类型的房间,例如单人间、双人间、三人间、总统套房等等,不同类型的房间就是不同数据类型的变量

酒店的每个房间就是变量,房间的编号就是变量名,房间的旅客就是变量值(数据值),房间的旅客会随着时间的变化而变化

  • 数据类型:数据类型可以是Java的基本数据类型引用数据类型,数据类型的作用就是在内存空间存储数据的时候添加类型的限制,以及限制内存空间的大小。例如数据类型是int,那么表示内存空间只能存储4个字节的整数类型

  • 变量名:变量名表示内存空间的名字,可以通过变量名访问内存空间,从而操作内存空间存储的内容(数据),变量名在命名的时候需要严格遵守标识符的命名规则和命名规范

  • 变量值(数据值):变量值可以是数据类型对应的字面值,例如数据类型是int,那么变量值可以是100,200这种整数类型的字面值,变量值还可以是变量(变量名)

3.1.3 变量使用场景

Q:什么时候会使用到变量

A:①重复使用某个值 ②某个数据经常发生改变

使用场景1: 用户登录

用户登录的时候,每个用户输入的账号名和登录密码是不相同的,那么如果我们想要去开发一个登录程序,那么需要两个变量来存储用户的登录信息,分别是存储账号名和登录密码

image

使用场景2:微信钱包余额

微信钱包余额是经常发生变化的,例如购物使用微信支付那么就扣微信钱包余额的钱,

我们就可以使用一个变量来存储微信钱包余额,当余额发生变化的时候,就修改变量存储的余额

image

3.1.4 变量分类

变量分类可以按照数据类型声明的位置两种方式分类

image

  1. 变量按照数据类型分类

Java的数据类型可以分成基本数据类型引用数据类型两大类

Java基本数据类型一共有8种

  • byteshortintlong表示四种整数类型

  • floatdouble 表示两种浮点类型(小数)

  • char表示字符类型

  • boolean表示布尔类型

通常都会将byteshortintlongfloatdoublechar统称为数值类型

每种基本数据类型分别使用不同的关键字表示

每种基本数据类型都有不同的取值范围以及占据不同的内存空间,内存空间的基本单位是字节(Byte)

image

每种基本数据类型能够参与的运算也是不一样的,例如数值型可以参与算术运算,而布尔类型可以参与关系运算,逻辑运算。

image

Java引用数据类型包括如下几种

  • 数组(array)

  • 类(class)

  • 接口(interface)

  • 枚举(enum)

  • 注解(annotation)

  • 记录(record)

Java引用数据类型的大小统一为 4 个字节,存储的是其引用对象的地址

目前Java小白(初学者)只需要掌握基本数据类型的使用,而引用数据类型会在面向对象相关章节详解。

  1. 变量按照声明的位置分类
  • 在方法体外,类体内声明的变量叫成员变量
 package net.ittimeline.java.core.foundational.syntax.variable.location;
    
    /**
     * 成员变量的定义和使用
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/8 10:37
     * @since Java17
     */
    public class MemberVariable {
    
        public static void main(String[] args) {
            Student student = new Student();
            student.name = "tony";
            student.age = 30;
            System.out.println("学生信息如下:");
            System.out.print("学生姓名:" + student.name);
            System.out.print("学生年龄:" + student.age);
    
        }
    }
    
    class Student {
        //在方法体外,类体内声明的变量叫成员变量
        /**
         * 学生姓名
         */
        String name;
        /**
         * 学生年龄
         */
        int age;
    
    }

程序运行结果

image

  • 在方法体外,类体内声明的变量并且使用static关键字修饰的成员变量叫静态变量
 package net.ittimeline.java.core.foundational.syntax.variable.location;
    
    /**
     * 静态变量的定义和使用
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/8 10:37
     * @since Java17
     */
    public class StaticVariable {
    
        //在方法体外,类体内声明的变量并且使用static关键字修饰的成员变量叫静态变量=
        /**
         * 默认国籍
         */
        static String DEFAULT_NATIONALITY = "Chinese";
    
        public static void main(String[] args) {
            //本类的main方法中直接使用变量名可以访问静态变量
            System.out.println("默认的国家是" + DEFAULT_NATIONALITY);
        }
    
    }
    

程序运行结果

image

  • 在方法体内或者代码块内声明的变量叫局部变量

package net.ittimeline.java.core.foundational.syntax.variable.location;

/**

  • 局部变量的定义和使用

  • @author tony 18601767221@163.com

  • @version 2023/7/8 10:36

  • @since Java17
    */
    public class LocalVariable {
    public static void main(String[] args) {
    //在方法体内声明的变量叫局部变量
    int number = 10;
    System.out.println("number = " + number);

     //在代码块内声明的变量叫局部变量
     {
         int value = 100;
         System.out.println("value = " + value);
     }
    

    }
    }

程序运行结果

image

目前Java小白(初学者)只要会使用局部变量即可,而成员变量和静态变量会在面向对象相关章节详解。

3.2 变量使用

Java语言是强类型的语言,强类型的含义是变量必须要先声明,再使用。而且指定类型的变量只能接受类型与之匹配的值。

变量声明的语法格式

数据类型 变量名;

变量声明以后,我们就可以给变量赋值

变量赋值的语法格式

变量名 = 变量值;

= 表示赋值运算符,也就是将=右边的变量值赋值给左边的变量

第一次赋值也会成为变量初始化

有时候我们会将变量的声明、赋值写在一行,也就是变量的定义

变量定义的语法格式

数据类型 变量名 = 变量值;

Q:什么时候使用变量的声明,什么时候使用变量的定义?

A:当不知道变量赋什么初始值的时候使用变量的声明,当知道变量赋什么初始值的时候使用变量的定义

Variable.java演示变量的声明、赋值、定义、三种使用方式

 package net.ittimeline.java.core.foundational.syntax.variable;
    
    /**
     * 变量的声明、赋值、定义、三种使用方式
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/8 11:18
     * @since Java17
     */
    public class Variable {
        public static void main(String[] args) {
            /*************************变量的声明与赋值*************************/
            /*
                变量的声明语法格式
                数据类型 变量名;
                数据类型:限制变量存储的数据类型,例如int表示整数,double表示小数
                变量名:表示存储空间的名字,根据变量名找到存储空间
             */
    
            //声明一个整数类型的变量,变量名是age,变量的类型是整数类型
            int age;
    
            /*
                变量赋值的语法格式
                变量名 = 变量值;
                等号(=):赋值运算符,用于将=右边的值赋值给左边的变量
             */
            age = 18;
            /*************************变量的三种使用方式*************************/
    
            //变量的使用方式1:打印输出变量,打印变量名就是打印变量名代表的内存空间
            System.out.println(age);
    
            //为了让输出结果更加直观 采用字符串拼接的方式打印变量 +表示字符串拼接,因为+左边是字符串
            System.out.println("age = " + age);
    
            //变量的定义:数据类型 变量名 = 变量值;
            //变量的使用方式2:修改变量的值
            int number = 10;
            System.out.println("第一次赋值的结果是" + number);
            // 修改变量的值 原来的值会被覆盖 变量同时只能存储一个值
            number = 100;
            System.out.println("修改变量的值结果是" + number);
    
    
            //变量的使用方式3:参与运算
            int left = 10;
            int right = 20;
            //将10和20相加的结果赋值给result
            int result = left + right;
            System.out.println("result = " + result);
    
    
            //变量在赋值的时候除了可以赋数据类型对应的字面值,
            int value = 10;
            //还可以将另外一个变量赋值给变量
            int copyValue = value;
            System.out.println("copyValue = " + copyValue);
        }
    }
    

程序运行结果

image

3.3 变量使用注意事项

  1. 变量在使用之前必须要定义,也就是必须要声明和赋值

package net.ittimeline.java.core.foundational.syntax.variable;

/**

  • 变量使用注意事项1. 变量在使用之前必须要定义,也就是必须要声明和赋值
  • @author tony 18601767221@163.com
  • @version 2023/7/8 11:23
  • @since Java17
    */
    public class VariableErrorExample1 {
    public static void main(String[] args) {
    // 变量name没有声明
    // System.out.println("name = "+name);
    //声明一个变量name
    String name;
    // 可能尚未初始化变量name
    System.out.println("name = " + name);
    }
    }

程序运行结果:编译错误

image

  1. 同一个作用域范围内的变量不能重复定义,例如main方法中不能定义同名的变量
package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 变量的使用注意事项2. 同一个作用域范围内的变量不能重复定义
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/8 11:26
 * @since Java17
 */
public class VariableErrorExample2 {
    public static void main(String[] args) {
        String name = "jack";
        String name = "tom";
    }
}

程序运行结果:编译错误

image

  1. 变量只能在定义的作用域范围内使用
package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 变量使用注意事项3:变量只能在定义的作用域范围内使用
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/8 11:28
 * @since Java17
 */
public class VariableErrorExample3 {
    public static void main(String[] args) {
        //局部代码块
        {
            int age = 18;

        }
        //超过了age所在的作用域范围
        System.out.println("age = " + age);
    }
}

程序运行结果:编译错误

image

  1. 变量值在赋值时,必须满足(兼容)变量的数据类型,并且在数据类型有效的范围内变化
package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 变量使用注意事项4:变量值在赋值时,必须满足(兼容)变量的数据类型,并且在数据类型有效的范围内变化
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/8 11:30
 * @since Java17
 */
public class VariableErrorExample4 {
    public static void main(String[] args) {

        //字符串字面量"18"是String类型,因此不能赋值给变量age
        // 不兼容的类型: java.lang.String无法转换为int
        int age = "18";
        // 整数字面量100 默认是int类型,因此可以赋值给变量value
        int value = 100;

        //兼容
        // 整数字面量18是int类型
        // 变量bigValue是long类型
        // long类型是占据8个字节,int占据4个字节
        long bigValue = 18;

        //100L是long类型的字面量
        // maxValue是int类型
        //不能将long类型的变量值赋值给int类型的变量
        int maxValue = 100L;
    }
}

程序运行结果:编译错误

image

  1. 一条语句可以定义多个变量 但是不推荐使用 可读性比较差
  package net.ittimeline.java.core.foundational.syntax.variable;
    
    /**
     * 变量使用注意事项5:一条语句可以定义多个变量 但是不推荐使用 可读性比较差
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/8 12:54
     * @since Java17
     */
    public class VariableDefinitionMulti {
        public static void main(String[] args) {
            //一条语句可以定义多个变量,中间使用逗号(,)分隔
            int left = 10, middle = 20, right = 30;
            System.out.println("left = " + left);
            System.out.println(middle);
            System.out.println("right = " + right);
        }
    }
    

程序运行结果

image

4. 标识符和关键字

4.1 关键字和保留字

关键字表示被 Java 语言赋予了特殊含义,用作专门用途的字符串(或单词),例如package,public,class,static,void,int等等

Java语言一共有50个关键字,50个关键字的特点是都是小写字母的英文单词

image

Oracle的官方文档中列出了所有的Java关键字

image

在常见的编辑器(Visual Studio)、IDE(IntelliJ IDEA)中针对关键字都会有特殊的颜色标记,非常直观。

IntelliJ IDEA中Java源文件中的关键字是橙色

image

除此以外还有三个特殊值:true、false、null ,它们不是关键字,因此不在关键字列表中,但是有特殊的意义,实际上是字面量(Literal),可以用来给变量赋值。

image

Keywords.java演示Java三个特殊值的使用方式:给变量赋值

package net.ittimeline.java.core.foundational.syntax;

/**

  • Java的三个特殊值

  • @author tony 18601767221@163.com

  • @version 2023/7/8 13:00

  • @since Java17
    */
    public class Keywords {
    public static void main(String[] args) {
    //三个特殊值 true,false,null的使用
    //true和false只能赋值给boolean类型的变量
    boolean flag = true;
    System.out.println("flag = " + flag);

     flag = false;
     System.out.println("flag = " + flag);
    
     //null只能赋值给引用数据类型,例如类
     //String表示类,对应的源文件是String.java
     String str = null;
     System.out.println("str = " + str);
    

    }
    }

程序运行结果

image

保留字就是现有Java版本尚未使用,但是可能以后的版本会作为关键字使用,例如const,goto就是Java语言中的保留字。它俩是C语言中的关键字,但是Java没有使用它,因为Java的底层需要调用C语言,为了兼容C语言的关键字,因此将goto和const作为保留字。

4.2 标识符

4.2.1 标识符介绍

Java程序中对包名类名(接口名、枚举名、注解名)、常量名变量名方法名等等命名的时候使用的字符序列(字符串)称为标识符(Identifier),通俗点说就是在写Java程序的时候凡是需要取名字的地方就是标识符。标识符命名要严格遵守命名规则和命名规范。

4.2.2 标识符命名规则

如果不遵守标识符的命名规则,程序无法编译通过,因此需要严格遵守

  1. 标识符由26个英文字母(大小写都可以)、数字(0-9)、下划线()、美元符$组成,不会的单词可以使用有道词典查询

  2. 标识符不能以数字开头

  3. 标识符不能使用关键字、保留字、特殊值,但是可以包含关键字、保留字、特殊值

  4. 标识符严格区分大小写,长度无限制,例如name和Name是完全不同的含义

4.2.3 标识符命名规范

如果不遵守标识符的命名规范,程序是可以编译通过的。

但是必须严格遵守,因为软件开发是团队协作,遵守标识符的命名规范可以增强程序的可读性,方便程序后期维护

  1. 标识符必须见名知意,不建议使用中文、拼音

  2. 标识符长度没有限制,但是不宜太长

  3. 包名:单词全部小写,多个单词之间使用.分割,通常都是公司域名倒过来的,例如com.taobao,com.alipay,com.baidu,com.tencent,com.huawei等等

  4. 类名(接口名、枚举名、注解名) :采用大驼峰命名法:第一个单词首字母大写,第二个及其以后的单词首字母大写,其他字母小写,例如HelloWorld,UserInfo等等

  5. 变量名、方法名:采用小驼峰命名法:第一个单词首字母小写,第二个及其以后的单词首字母大写,其他字母小写。例如userName,getUserName,setUserName等等。

  6. 常量:单词字母全大写,多个单词之间使用下划线分隔,例如DEFAULT_PASSWORD,DEFAULT_SIZE等等。

4.2.4 标识符命名案例

以下合法的标识符是?

标识符名称是否合法
flag_3
my code否 不能有空格,只能是字母、数字、下划线
discount%否 百分号不能作为标识符的组成部分
234rate否 数字不能开头
$name
println
main

Identifier.java演示标识符的命名规则和命名规范

package net.ittimeline.java.core.foundational.syntax;

/**

  • 标识符的命名规则和命名规范
  • @author tony 18601767221@163.com
  • @version 2023/7/8 13:11
  • @since Java17
    */
    public class Identifier {
    }
    /类名的命名规则和命名规范/

/**

  • 用户信息
    */
    class UserInfo {
    /常量的命名规则和命名规范/

    /**

    • 默认密码
      */
      public static final String DEFAULT_PASSWORD = “111111”;

    /变量的命名规则和命名规范/

    /**

    • 用户名
      */
      private String userName;

    /**

    • 密码
      */
      private String password;

    /方法的命名规则和命名规范/

    public String getUserName() {
    return userName;
    }

    public void setUserName(String userName) {
    this.userName = userName;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }
    }

5. 基本数据类型

5.1 整数类型

5.1.1 整数类型介绍

整数类型简称整型

整型是日常生活中经常使用的类型,例如描述人的年龄,大楼的层数,年份等等。

Java语言的整型按照内存空间和取值范围分成byte、short、int、long,绝大部分场景下推荐使用int和long,因为不会越界(超过取值范围)。

在使用整数类型的时候,需要注意不要超过数据类型的取值范围(最大值,最小值),否则程序会发生错误

image

IntegerLimits.java演示四种整数类型的取值范围以及占据的内存空间

 package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * 四种整数类型的取值范围和内存空间
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/9 9:44
     * @since Java17
     */
    public class IntegerLimits {
        public static void main(String[] args) {
            //byte对应的包装类是Byte,可以调用Byte类的静态成员获取byte类型的极限和占据的内存空间
            System.out.println("byte所能存储的最大值是" + Byte.MAX_VALUE + " byte所能存储的最小值是" + Byte.MIN_VALUE + " byte占据的内存空间是" + Byte.BYTES + "个字节");
    
            //short对应的包装类是Short,可以调用Short类的静态成员获取short类型的极限和占据的内存空间
            System.out.println("short所能存储的最大值是" + Short.MAX_VALUE + " short所能存储的最小值是" + Short.MIN_VALUE + " short占据的内存空间是" + Short.BYTES + "个字节");
    
            //int对应的包装类是Integer,可以调用Integer类的静态成员获取int类型的极限和占据的内存空间
            System.out.println("int所能存储的最大值是" + Integer.MAX_VALUE + " int所能存储的最小值是" + Integer.MIN_VALUE + " int占据的内存空间是" + Integer.BYTES + "个字节");
    
            //long对应的包装类是Long,可以调用Long类的静态成员获取long类型的极限和占据的内存空间
            System.out.println("long所能存储的最大值是" + Long.MAX_VALUE + " long所能存储的最小值是" + Long.MIN_VALUE + " long占据的内存空间是" + Long.BYTES + "个字节");
        }
    }
    

程序运行结果

image

5.1.2 整数类型使用

IntegerVariable.java演示四种整数类型使用

  • 定义long类型的变量赋值时需要使用L或者l作为后缀

  • Java程序中整数变量通常使用int类型,除非int不够用时才会使用long

  • Java整数字面量默认是int类型

  package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * 整数类型的使用
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/9 9:52
     * @since Java17
     */
    public class IntegerVariable {
        public static void main(String[] args) {
    
            /**********************byte类型变量的使用**********************/
            //整数字面量12是int类型,但是在byte的取值范围之内,因此赋值成功
            byte byteVar = 12;
            System.out.println("byteVar = " + byteVar);
            //字面量129默认是int类型,但是不在byte的取值范围之内,因此赋值失败
            //byteVar=129;
    
            /**********************short类型变量的使用**********************/
            //整数字面量1200是int类型,但是在short的取值范围之内,因此赋值成功
            short shortVar = 1200;
            //整数字面量120000是int类型,但是不在short的取值范围之内,因此赋值失败
            //shortVar = 120000;
            System.out.println("shortVar = " + shortVar);
    
    
            /**********************int类型变量的使用**********************/
            //120000是int类型,因为120000在int的取值范围内,所以赋值成功
            int intVar = 120000;
            System.out.println("intVar = " + intVar);
            //整数字面量12000000000默认还是int类型,但是超过int的取值范围,因此赋值失败
            //intVar=120_0000_0000;
    
            /**********************long类型变量的使用**********************/
            //整数类型字面量取值范围只能在int的取值范围,12000000000超过int的取值范围因此赋值失败
            //long longVar=120_0000_0000;
            //整数类型字面量12000000000L是long类型,而且在long的取值范围内,因此赋值成功
            long longVar = 120_0000_0000L;
            System.out.println("longVar = " + longVar);
            //long类型整数类型字面量取值范围只能在long的取值范围,12000000000000000000000L超过long的取值范围,因此赋值失败
            //longVal = 120_0000_0000_0000_0000_0000L;
    
        }
    }
    

程序运行结果

image

5.1.3 整数字面量的四种进制表示

在Java语言中,整数字面量支持四种进制表示方式

  1. 二进制(binary):由0和1组成,二进制的整数字面量是以0b或者0B开头,例如0b1101,Java7以后支持

  2. 八进制(octal):由0-7之间的八个整数组成,八进制的整数字面量是以0开头,例如017

  3. 十进制(decimal):由0-9之间的十个整数组成,整数字面量默认的进制就是十进制,例如100

  4. 十六进制(hex):由0-9之间的十个整数以及a-f之间6个小写字母或者是A-F之间的6个大写字母组成,十六进制的整数字面量是以0x或者0X开头,例如0x1f

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 整数字面量四种进制的表示
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/9 15:20
 * @since Java17
 */
public class IntegerLiteralBinaryOctalDecimalHex {
    public static void main(String[] args) {
        // System.out.println()打印语句打印整数变量或者是整数字面量默认是十进制

        // 二进制的整数字面量的使用
        byte binary = 0B1101;
        System.out.println("二进制0B1101转换为十进制的结果是" + binary);


        //八进制的整数字面量的使用
        byte octal = 017;
        System.out.println("八进制017转换成十进制的结果是" + octal);

        //十进制的整数字面量的使用
        //100默认就是十进制
        int decimal = 100;
        System.out.println("decimal = " + decimal);

        //十六进制的整数字面量的使用
        int hex = 0x1f;
        System.out.println("十六进制0x1f转换成十进制的结果是" + hex);
    }
}

程序运行结果

image

Java的Integer和Long提供了整数的四种进制查看方式

IntegerVariableBinaryOctalDecimalHex.java演示整数的四种进制查看方式

  package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * 整数的四种进制查看方式
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/17 8:37
     * @since Java17
     */
    public class IntegerVariableBinaryOctalDecimalHex {
        public static void main(String[] args) {
            int number = 25;
            System.out.println("25的二进制补码表示方式为" + Integer.toBinaryString(number));
            System.out.println("25的八进制补码表示方式为" + Integer.toOctalString(number));
            System.out.println("25的十进制补码表示方式为" + number);
            System.out.println("25的十六进制补码表示方式为" + Integer.toHexString(number));
    
            number = -25;
            System.out.println("-25的二进制补码表示方式为" + Integer.toBinaryString(number));
            System.out.println("-25的八进制补码表示方式为" + Integer.toOctalString(number));
            System.out.println("-25的十进制补码表示方式为" + number);
            System.out.println("-25的十六进制补码表示方式为" + Integer.toHexString(number));
        }
    }
    

程序运行结果

image

5.1.4 整数字面量使用下划线

如果Java源文件中存在着很长的整数字面量值,不易阅读,此时可以使用Java7以后新增的特性:数值字面量使用下划线来分割数值,使得数值更加容易阅读。

我们可以在整数数值之间使用下划线,但是编译器在编译的时候会删除下划线。

image

IntegerLiteralUnderScore.java演示下划线在整数字面量的使用

 package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * 整数字面量使用下划线
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/10 9:02
     * @since Java17
     */
    public class IntegerLiteralUnderScore {
        public static void main(String[] args) {
            long quantity = 90_0000_0000L;
            System.out.println("2037年世界人口总数可能将达到" + quantity + "人");
        }
    }

程序运行结果

image

5.1.5 整数在内存中的存储

IntegerMemoryStorage.java演示将整数字面量3赋值给不同类型的整数变量

   package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * 不同类型的整数在内存中的存储
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/10 9:09
     * @since Java17
     */
    public class IntegerMemoryStorage {
        public static void main(String[] args) {
            byte byteVar = 3;
            System.out.println("byteVar = " + byteVar);
    
            short shortVar = 3;
            System.out.println("shortVar = " + shortVar);
    
            int intVar = 3;
            System.out.println("intVar = " + intVar);
    
            long longVar = 3;
            System.out.println("longVar = " + longVar);
        }
    }
    

程序运行结果

虽然程序输出结果都是3

image

但是它们在内存中占据的空间不同,因此存储形式也是不同,数据在内存中都是以二进制形式存储

image

整数底层使用二进制补码形式存储,要了解补码需要先了解原码和反码

原码:最高位是符号位,0表示正数,1表示负数,其他位表示数值位

例如一个字节(8个二进制位)整数25

25的原码:0001 1001

-25的原码:1001 1001

反码:正数的反码与原码一致,负数的反码是原码的符号位不变,其他位取反

25的反码:0001 1001

-25的反码:1110 0110

补码:正数的补码与原码一致,负数的补码等于反码基础上加1

25的补码:0001 1001

-25的补码:1110 0111

整数25在内存中的存储

image

整数-25在内存中的存储

image

验证一个字节负整数-25在计算机底层的存储

image

5.1.6 一个字节存储数据的范围

Q:一个字节可以存储的数据范围

A:数据分为有符号和无符号两种

①无符号:不考虑负数,也就是只有0和正数

0000 0000 ~ 1111 1111转换成十进制也就是0 ~ 255

因此一个字节存储的无符号数据范围是0 ~ 255之间的256个整数

② 有符号:考虑负数,也就是包含负数,0和正数

正数部分 0000 0000 ~ 0111 1111 转换成十进制就是 0 ~ 127  
负数部分 1000 0001 ~ 1111 1111 转换成十进制就是 -127 ~ 1
特殊值   1000 0000             转换成十进制就是 -128,最高位既是符号位,又是数值位

因此一个字节存储的有符号数据范围是**-128 ~ 127**之间的256个整数

计算器验证-128在计算机底层的存储

image

5.1.7 整数溢出的内存原理

IntegerOverFlow.java演示在给整数变量赋值时如果超过数据类型的取值范围就会造成数据溢出

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 整数溢出的内存原理
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/10 9:26
 * @since Java17
 */
public class IntegerOverFlow {
    public static void main(String[] args) {
        /*
        //  计算机在执行运算的时候使用补码运算
           1. byte的表示范围是-128 - +127
           2. 135超过了byte的表示范围,在强制类型转换的时候会发生溢出
           3. 135 默认的类型是int int在内存中占据4个字节 1Byte=8bit 4个字节对应32位
           4. 135 在内存的二进制补码表示方式 0000 0000 0000 0000  0000 0000 1000 0111
           5. 因为135强制类型转换成byte 因此会从右往左截取8位,结果是1000 0111
           6. 1000 0111 占据1个字节,但是符号位(左边第一位)是1表示该数字是一个负数

        // 当我们查看计算机执行结果的时候使用原码 将1000 0111转换原码
            1. 根据补码得到反码:补码减1 1000 0111-1=1000 0110
            2. 根据反码得到原码:最高位不变,其他位取反 1000 0110  也就是 1111 1001
            3. 将原码1111 1001 转换成十进制-121
            4. 因此最后的结果是-121
         */


        byte value = (byte) 135;
        System.out.println("value = " + value);
    }
}

程序运行结果

image

image

5.2 浮点类型

5.2.1 浮点类型介绍

浮点类型就是生活中的小数,例如银行的利率,股市的涨跌指数等等都是浮点数

Java的浮点类型有固定的取值范围和占据的内存字节数,不受具体的OS影响,这样保证了跨平台的特性

Java的浮点类型分为单精度浮点型float双精度浮点型double两种

float占据四个字节(byte),也就是32位(bit)

double占据八个字节(byte),也就是64位(bit)

image

FloatLimits.java演示Java两种浮点类型的表示范围和占据内存字节数

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**

  • Java两种浮点类型的表示范围和占据内存字节数
  • @author tony 18601767221@163.com
  • @version 2023/7/10 9:30
  • @since Java17
    */
    public class FloatLimits {
    public static void main(String[] args) {
    //float的表示范围和占据的内存字节数
    // %f 表示该格式为浮点数 小数点后保留六位 %.10f 表示小数点保留10位
    // %d 表示该格式为整数
    // %e 表示该格式为科学计数法
    System.out.printf(“float所能存储的最大值是%e,float所能存储的最小值是%e,float占据的内存字节数是%d \n”, Float.MAX_VALUE, Float.MIN_VALUE, Float.BYTES);
    System.out.printf(“long所能存储的最大值是%d,long所能存储的最小值是%d,long占据的字节数量是%d \n”, Long.MAX_VALUE, Long.MIN_VALUE, Long.BYTES);
    System.out.printf(“double所能存储的最大值是%e,double所能存储的最小值是%e,double占据的内存字节数是%d \n”, Double.MAX_VALUE, Double.MIN_VALUE, Double.BYTES);
    }
    }

程序运行结果

image

5.2.2 浮点类型使用

浮点类型的字面量可以使用十进制和科学计数法两种方式表示

  • 十进制数:5.12,512.0f,.512,120.0

  • 科学计数法:1.2E2,31415926e-7

浮点类型的字面量默认类型是double类型,如果需要表示float类型的字面量,需要在float类型字面量结尾添加F或者f

可以将float类型的字面量赋值给double类型的变量,但是不能将double类型的字面量赋值给float类型的变量

FloatVariable.java演示浮点类型使用

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**

  • 浮点类型的使用

  • @author tony 18601767221@163.com

  • @version 2023/7/10 9:33

  • @since Java17
    */
    public class FloatVariable {
    public static void main(String[] args) {

     //十进制双精度浮点数
     double doubleVar = 120.0;
     System.out.println("doubleVar = " + doubleVar);
    
     //科学计数法的双精度浮点数
     doubleVar = 1.2E2;
     System.out.println("doubleVar = " + doubleVar);
    
     ///e-7表示10的-7次方
     double PI = 31415926e-7;
     System.out.println("PI = " + PI);
    
     //字面量3.14是double类型,因此不能直接赋值给float类型,因为 不兼容的类型: 从double转换到float可能会有损失
     //float floatVar = 3.14;
    
     //float类型字面量需要加f后缀
     float floatVar = 3.14f;
     System.out.println("floatVar = " + floatVar);
    
     //可以将float类型的字面量赋值给double类型的变量
     doubleVar = 3.14f;
     System.out.println("doubleVar = " + doubleVar);
    

    }
    }

程序运行结果

image

5.2.3 浮点类型的精度问题

我们在使用float或者double就会遇到精度问题

  • 并不是所有小数都可以精确地使用二进制浮点数表示,二进制浮点数不能精确地表示0.1,0.01,0.001这样10的负次幂

  • 浮点类型float、double的数据不适合在不容许舍入误差的金融领域(例如银行、保险、证券等行业),如果需要精确数字计算或者保留指定位数的精度,需要使用java.math.BigDecimal类

FloatPrecision.java演示单精度浮点类型float的精度问题,包括float类型字面量、变量以及运算相关的精度问题

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**

  • 单精度浮点类型float的精度问题,包括float类型字面量、变量以及运算相关的精度问题

  • @author tony 18601767221@163.com

  • @version 2023/7/10 10:00

  • @since Java17
    */
    public class FloatPrecision {

    public static void main(String[] args) {
    // 我们在使用float或者是double的变量或者是字面量的时候就会遇到精度问题

     //float占据4个字节 单精度浮点类型  可以表示6位有效数字(小数部分的6位数字)
    
     /**********************float类型字面量和变量的精度问题**********************/
     System.out.println(3.141592f);
     //3.1415926f是单精度浮点类型float类型的字面量,但是由于只能表示6位有效数字,因此输出结果是3.1415925
     System.out.println(3.1415926f);
    
     float floatVar = 3.141592f;
     System.out.println("floatVar = " + floatVar);
     floatVar = 3.1415926f;
     System.out.println("floatVar = " + floatVar);
    
     /**********************float类型字面量和变量的减法运算的精度问题**********************/
     float floatLeft = 2.0f;
     float floatRight = 1.22222f;
     float floatResult = floatLeft - floatRight;
     // floatResult = 0.77778006
     System.out.println("floatResult = " + floatResult);
    

    }
    }

程序运行结果

image

DoublePrecision.java演示单精度浮点类型float的精度问题,包括float类型字面量、变量以及运算相关的精度问题

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**

  • 双精度double的精度问题,包括double类型字面量、变量以及运算的精度问题

  • @author tony 18601767221@163.com

  • @version 2023/7/10 10:21

  • @since Java17
    */
    public class DoublePrecision {
    public static void main(String[] args) {
    //double占据8个字节 双精度浮点类型 可以表示15位有效数字(小数部分的15位数字)

     /**********************double类型字面量和变量的精度问题**********************/
     System.out.println(3.141592653589793);
     //3.1415_9265358979323846是双精度浮点类型double类型的字面量,但是由于只能表示15位有效数字,因此输出结果是3.141592653589793
     System.out.println(3.1415_9265358979323846);
    
    
     // 3.141592653589793在double类型的有效数字范围
     double dblVar = 3.141592653589793;
     System.out.println("dblVar = " + dblVar);
    
     // 3.14159265358979323846超过了double类型的有效数字范围
     dblVar = 3.14159265358979323846;
     System.out.println("dblVar = " + dblVar);
    
    
     /**********************double类型变量减法运算的精度问题**********************/
     //
     double doubleLeft = 2.0;
     double doubleRight = 0.9999_999;
     double doubleResult = doubleLeft - doubleRight;
     System.out.println("doubleResult = " + doubleResult);
    
     /**********************double类型变量相等性判断精度问题**********************/
     double doubleSource = 2.7;
     double doubleTarget = 8.1 / 3;
    
     System.out.println("doubleTarget = " + doubleTarget);
    
     //当对运行结果是小数进行相等性判断时,需要注意
     // doubleSource和doubleTarget并不相等
     if (doubleSource == doubleTarget) {
         System.out.println("doubleSource和doubleTarget两个浮点类型的变量值相等");
     }
    
     //应该是以两个数的差值绝对值,在某个精度范围内判断
     if (Math.abs(doubleSource - doubleTarget) < 0.000001) {
         System.out.println("doubleSource和doubleTarget两个变量差值的绝对值是" + Math.abs(doubleSource - doubleTarget));
         System.out.println("doubleSource和doubleTarget两个浮点类型的变量值误差非常小,认为相等");
    
     }
     //如果是直接赋值的小数那么是可以使用==判断相等性
     doubleTarget = 2.7;
     if (doubleSource == doubleTarget) {
         System.out.println("doubleSource和doubleTarget两个浮点类型的变量值相等");
     }
    

    }
    }

程序运行结果

image

5.2.4 浮点数字面量使用下划线

如果Java源文件中存在着很长的整数字面量值,不易阅读,此时可以使用JDK7以后新增的特性:数值字面量使用下划线来分割数值,使得数值更加容易阅读。

我们可以在浮点数的数值之间使用下划线,但是编译器在编译的时候会删除下划线。

image

FloatUnderScore.java演示在小数字面量使用下划线

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 浮点数字面量使用下划线
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/10 10:44
 * @since Java17
 */
public class FloatLiteralUnderScore {
    public static void main(String[] args) {
        double dblVar = 3.14159_26535_89793;
        System.out.println("dblVar = " + dblVar);

    }
}

程序运行结果

image

5.2.5 浮点类型案例

浮点类型案例1:

需求:定义圆周率并赋值为3.14,现有3个圆的半径分别是1.2,2.5,6,求它们的面积

DoubleExample1RoundArea.java演示浮点类型案例1需求的实现过程

 package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * double数据类型案例1:
     * 需求:定义圆周率并赋值为3.14,现有3个圆的半径分别是1.2,2.5,6,求它们的面积
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/12 17:01
     * @since Java17
     */
    public class DoubleExample1RoundArea {
        public static void main(String[] args) {
            //定义变量PI存储圆周率
            double PI = 3.14;
    
            double firstRadius = 1.2;
            double firstArea = PI * firstRadius * firstRadius;
            System.out.println("第1个圆的半径是" + firstRadius + " 第1个圆的面积是" + firstArea);
    
            double secondRadius = 2.5;
            double secondArea = PI * secondRadius * secondRadius;
            System.out.println("第2个圆的半径是" + secondArea + " 第2个圆的面积是" + secondArea);
    
            double thirdRadius = 6;
            double thirdArea = PI * thirdRadius * thirdRadius;
            System.out.println("第3个圆的半径是" + secondArea + " 第3个圆的面积是" + thirdArea);
    
    
        }
    }

程序运行结果

image

浮点类型案例2:

需求:小明要到美国旅游,可是那里的温度是以华氏度为单位记录的。 他需要一个程序将华氏温度(80 度)转换为摄氏度,并以华氏度和摄氏度为单位分别显示该温度

DoubleExample2Fahrenheit2DegreeCentigrade.java演示浮点类型案例2的需求实现过程

  package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * 浮点类型案例2:小明要到美国旅游,可是那里的温度是以华氏度为单位记录的。 它需要一个程序将华氏温度(80 度)转换为摄氏度,并以华氏度和摄氏度为单位分别显示该温度
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/12 17:08
     * @since Java17
     */
    public class DoubleExample2Fahrenheit2DegreeCentigrade {
        public static void main(String[] args) {
            //华氏温度为80℉
            double fahrenheit = 80.0;
            //华氏温度转换为摄氏温度
            double degreeCentigrade = (fahrenheit - 32) / 1.8;
    
            System.out.println("华氏温度" + fahrenheit + "℉" + "对应的摄氏温度是" + degreeCentigrade + "℃");
    
    
        }
    }

程序运行结果

image

5.2.6 浮点类型在内存中的存储

如果你明白了小数在内存中的存储形式,那么就能够知道以下问题的答案

  1. 为什么4个字节的float比8个字节的long存储数据范围大

  2. 为什么8个字节的double比四个字节的float精度更高

  3. 为什么float和double会有精度问题

由于浮点数的存储机制和整数存储不一样,Java的浮点类型遵守IEEE754标准,采用二进制的科学计数法表示浮点数。

对于float,第1位是符号位,接下来8位表示指数位,接下来23位表示尾数位

对于double,第1位是符号位,接下来11位表示指数位,接下来52位表示尾数位

image

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

指数位:把十进制小数转换为二进制小数形式,小数点(左右)移动到其左边只保留一位有效数字,小数点移动的位数加上127,得到指数位值。(左移位数为正,右移位数为负数)

尾数部分:小数点右侧的小数部分的二进制表示

案例:四字节十进制小数3.625在内存中是如何以二进制方式存储的?

  1. 将十进制小数转换为二进制小数

1.1 将小数点左边的整数部分转换为二进制,转换方式就是除2取余法:即不断地除以2得到余数,直到商数为0,再将余数倒着拼接起来即可,3转换为二进制的结果是11

1.2 将小数点右边的小数部分转换为二进制,转换方式就是将小数部分乘以2的计算结果取整数部分,直到计算结果的小数为0为止

0.625*2=1.25 取整数部分1
0.25*2=0.5  取整数部分0            
0.5*2=1.0   取整数部分1

此时1.0小数部分就是0

0.625转换为二进制的结果就是101

3.625转换为二进制的结果是11.101

2.将二进制小数使用科学计数法表示

科学计数法:整数部分只有1位,并且非0

例如十进制586472.564使用科学计数法表示为5.86473564*10^5

例如十进制0.0000568使用科学计数法表示为0.568*10^-5

二进制11.101使用科学计数法表示位1.1101*2^1

11.101需要将小数点向左移动1位保证小数点左边有一位有效数字,移动的结果是1.1101*2^1

最终所有二进制小数使用科学计数法表示以后,它们的整数部分都是1**,**即小数点左边只有一个1,所以不用存储1和小数点。

符号位:**3.625是正数,因此符号位是0,**正数表示0,负数表示1

指数位:127+1(左移1位)=128,转换为二进制1000 0000

尾数位:1101,不足23位部分补充0,即1101 0000 0000 0000 0000 000

十进制四字节小数3.625在内存中是采用如下二进制存储,也就是0 1000 0000 1101 0000 0000 0000 0000000

image

案例:四字节十进制小数0.9在内存中是如何以二进制方式存储的?

  1. 将十进制小数转换为二进制小数

1.1 将小数点左边的整数部分转换为二进制,转换方式就是**除2取余法:即不断地除以2得到余数,直到商数为0,再将余数倒着拼接起来即可,**0转换为二进制的结果是还是0

1.2 将小数点右边的小数部分转换为二进制,转换方式就是将小数部分乘以2的计算结果取整数部分,直到计算结果的小数为0为止

0.9*2=1.8 取1

0.8*2=1.6 取1
0.6*2=1.2 取1
0.2*2=0.4 取0
0.4*2=0.8 取0

0.8*2=1.6 取1
0.6*2=1.2 取1
0.2*2=0.4 取0
0.4*2=0.8 取0
......

以此类推将会陷入无限循环,但四个字节的尾数位只有23位,超过部分会舍弃,因此会存在误差,存储的近似值

因此十进制小数0.9转换为二进制结果为0.1 11001100 110011001100 110

  1. 将二进制小数使用科学计数法表示

科学计数法:整数部分只有1位,并且非0

例如十进制586472.564使用科学计数法表示为5.86473564*10^5

例如十进制0.0000568使用科学计数法表示为0.568*10^-5

0.1 11001100110011001100 110需要将小数点右移1位,保证小数点左边一位有效数字1,右移一位的结果就是1.1100 1100 1100 1100 1100 110*10^-1

最终所有二进制小数使用科学计数法表示以后,它们的整数部分都是1**,**即小数点左边只有一个1,所以不用存储1和小数点。

符号位:0,0.9是正数,0表示正数,1表示负数

指数位:127-1(右移1位)=126,转换成二进制是0111 1110

尾数位:1100 1100 1100 1100 1100 110

十进制四字节小数0.9在内存中是采用如下二进制存储,也就是00111 1110 1100 1100 1100 1100 1100 110

image

FloatBinary.java演示查看浮点数的二进制方式

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 查看浮点数的二进制表示
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/19 12:27
 * @since Java17
 */
public class FloatBinary {
    public static void main(String[] args) {
        float floatValue = 3.625f;
        System.out.println("四个字节的小数3.625的二进制表现形式是" + Integer.toBinaryString(Float.floatToIntBits(floatValue)));
        double doubleValue = 3.625;
        System.out.println("八个字节的小数3.625的二进制表现形式是" + Long.toBinaryString(Double.doubleToLongBits(doubleValue)));

        floatValue = 0.9f;
        System.out.println("四个字节的小数0.9的二进制表现形式是" + Integer.toBinaryString(Float.floatToIntBits(floatValue)));

        doubleValue = 0.9;
        System.out.println("八个字节的小数0.9的二进制表现形式是" + Long.toBinaryString(Double.doubleToLongBits(doubleValue)));

    }
}

程序运行结果

image

计算机在存储浮点数时尾数部分可能会丢失,造成精度损失(小数都是近似值)

FloatArithmetic.java演示浮点数运算的精度问题

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 浮点数的算术运算精度问题
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/19 15:13
 * @since Java17
 */
public class FloatArithmetic {
    public static void main(String[] args) {
        float floatX = 1.0f;
        float floatY = 0.9f;
        //由于0.9在内存中无法用二进制小数精确存储,因此无法获取精确的计算结果
        float result = floatX - floatY;
        System.out.println("result = " + result);
    }
}

程序运行结果

image

Q:为什么4个字节的float比8个字节的long存储数据范围大

A: 因为float占据四个字节,也就是32位,其中1位是符号位,8位是指数位,23位是尾数位,float的最大值是2的128次方(2128),最小值是2的-148次方(2-149)

 package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * float和long的取值范围指数表示
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/19 17:37
     * @since Java17
     */
    public class FloatLongExponent {
        public static void main(String[] args) {
    
            System.out.println("2的128次方结果是" + Math.pow(2, 128));
            //float的最大值是2的128次方
            System.out.println("float的最大值是" + Float.MAX_VALUE);
    
            System.out.println("float的最小值是" + Float.MIN_VALUE);
            //float的最小值是2的-149次方
            System.out.println("2的-149次方结果是" + Math.pow(2, -149));
    
    
            System.out.println("long的最大值是" + Long.MAX_VALUE);
            System.out.println("2的63次方减1的结果是" + (Math.pow(2, 63) - 1));
    
    
            System.out.println("long的最小值是" + Long.MIN_VALUE);
            System.out.println("-2的63次方的结果是" + (Math.pow(-2, 63)));
    
    
        }
    }
    

程序运行结果

image

Q:为什么8个字节的double比四个字节的float精度更高,取值范围更大

A:因为double有52位尾数位,float只有23位尾数,因此double的精度高于float,double有11位指数,float只有8位指数,因此double的取值范围大于float

Q:为什么float和double会有精度问题

A:因为有些数字无法精确用二进制表示,例如4个字节的小数0.9使用二进制的科学计数法表示时尾数位只能有23位,但是0.9转换为二进制的科学计数表示时有无限个尾数位,超过23位会被截断(舍弃),因此float和double会有精度问题

5.3 字符类型

5.3.1 字符类型介绍

字符类型就是用于描述单个字符的数据类型,在Java语言中的字符字面量使用一对单引号(‘’)包含起来。

字符类型字面量有四种表现方式

  1. 使用一对单引号(‘’)包含的单个字符(字母、数字、汉字、符号),例如’a’,‘1’,'中’等等

  2. 直接使用十六进制Unicode字符集编号表示,通常是’\uXXXX’,其中XXXX表示一个十六进制整数,例如’\u4e2d’,'\u6587’等等

  3. 转义字符:使用’’ 将其后的字符转变为特殊字符型字面量,例如’\n’,'\t’等等

  4. 直接使用十进制Unicode字符集编号表示,例如20013, 25991等等

在Java语言中使用char关键字表示字符类型,char占据2个字节内存空间,并且char没有符号位,表示数值范围是0-65535

 package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * 字符类型存储数据的取值范围和内存空间
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/10 17:05
     * @since Java17
     */
    public class CharacterLimits {
        public static void main(String[] args) {
            //char对应的包装类是Character,可以调用Character类的静态成员获取char类型的极限和占据的内存空间
            System.out.println("char所能存储的最大值是" + (int) Character.MAX_VALUE + " char所能存储的最小值是" + (int) Character.MIN_VALUE + " char占据的内存空间是" + Character.BYTES + "个字节");
            
        }
    }
    

程序运行结果

image

5.3.2 ASCII字符集

计算机底层只能够识别0和1组成的二进制序列,对于英文字母’a’,汉字’中’,转义字符 ‘\n’,Unicode字符集编码值’\u4e2d’等等字符不能满足该规则,因此这些字符数据不能直接在计算机中存储,但是现实生活中又有这样的需求,为了能够让这些字符数据存储在计算机中,可以给这些字符指定一个编号,这个编号就是**ASCII字符集,ASCII字符集采用ASCII编码。**ASCII编码表只有128个字符,用一个字节表示即可(也就是每个字符占据1个字节)。实际上一个字节的取值范围可以表示256个字符,但是ASCII只使用了128个。

ASCII编码对照表

image

ASCII字符集常用字符对应的编号以及二进制存储

   package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * ASCII字符集常用字符的码点(编号)以及二进制存储
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/19 20:06
     * @since Java17
     */
    public class CharacterCodePointBinary {
        public static void main(String[] args) {
            char[] chars = {'0', 'a', 'A', ' ', '\n',};
            System.out.println("字符0的码点(编号)是" + Character.codePointAt(chars, 0) + "二进制格式是" + Integer.toBinaryString(Character.codePointAt(chars, 0)));
            System.out.println("字符a的码点(编号)是" + Character.codePointAt(chars, 1) + "二进制格式是" + Integer.toBinaryString(Character.codePointAt(chars, 1)));
            System.out.println("字符A的码点(编号)是" + Character.codePointAt(chars, 2) + "二进制格式是" + Integer.toBinaryString(Character.codePointAt(chars, 2)));
            System.out.println("空格的码点(编号)是" + Character.codePointAt(chars, 3) + "二进制格式是" + Integer.toBinaryString(Character.codePointAt(chars, 3)));
            System.out.println("换行的码点(编号)是" + Character.codePointAt(chars, 4) + "二进制格式是" + Integer.toBinaryString(Character.codePointAt(chars, 4)));
        }
    }
    

程序运行结果

image

ASCII字符码点(编号)存储(二进制)
‘0’480011 0000
‘a’970110 0001
‘A’650100 0001
空格320010 0000
换行100000 1010

CharacterASCIIVariable.java演示ASCII字符集的使用

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

import java.nio.charset.Charset;

/**

  • ASCII字符集的使用

  • @author tony 18601767221@163.com

  • @version 2023/7/10 10:51

  • @since Java17
    */
    public class CharacterASCIIVariable {
    public static void main(String[] args) {
    /ASCII字符集常用字符的编码/
    char letterA = ‘a’;
    System.out.println("letterA = " + letterA);
    //(int) letterA 表示将字符类型转换为int类型,这样就可以获取字符对应的编码
    System.out.println("字符a对应的编码是 " + (int) letterA);
    //Charset.defaultCharset()用于获取当前JVM使用的编码
    //UTF-8编码兼容ASCII
    System.out.println(“当前JVM使用的编码是” + Charset.defaultCharset());

     char upperA = 'A';
     System.out.println("upperA = " + upperA);
     System.out.println("字符A对应的编码是 " + (int) upperA);
    
     char zero = '0';
     System.out.println("zero = " + zero);
     System.out.println("字符0对应的编码是 " + (int) zero);
    
    
     char space = ' ';
     System.out.println("space = " + space);
     System.out.println("字符空格对应的编码是 " + (int) space);
    
     //\n表示换行转义字符
     char newLine = '\n';
     System.out.println("Hello\nWorld");
     System.out.println("Hello" + "\n" + "World");
     System.out.println("字符'换行符'对应的编码是 " + (int) newLine);
    

    }
    }

程序运行结果

image

5.3.3 Unicode字符集

Unicode字符集是国际组织指定的可以容纳世界上所有国家的文字和符号的字符集方案,

每套字符集都至少有一套编码,例如Unicode字符集有UTF-8、UTF-32、UTF-16三种编码方案。Java的字符类型是采用Unicode字符集,因此Java程序可以支持各种语言的字符。

CharacterUnicodeVariable.java演示Unicode字符集的使用

  package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * Unicode字符集的使用
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/10 11:05
     * @since Java17
     */
    public class CharacterUnicodeVariable {
        public static void main(String[] args) {
            // Unicode支持中文
            //Unicode字符是以\u开头的十六进制
            char chinese = '\u4e2d';
            System.out.println("chinese = " + chinese);
            System.out.println("字符中对应的UTF-8编码的编号是" + (int) chinese);
            char language = '\u6587';
            System.out.println("世界上使用人口最多的语言是" + chinese + language);
            System.out.println("字符文对应的UTF-8编码的编号是" + (int) language);
    
            //char的本质就是一个整数,在默认输出时时Unicode编码对应的字符
            // 整数字面量20013和Unicode字符 '\u4e2d'是等价的
            chinese = 20013;
            // 整数字面量25991和Unicode字符 '\u6578'是等价的
            language = 25991;
            System.out.println("世界上使用人口最多的语言是" + chinese + language);
    
    
            //Unicode支持全世界所有国家的字符,例如韩文
            //韩文的你好是  안녕하세
            char helloFirstLetter = '안';
            char helloSecondLetter = '녕';
            char helloThirdLetter = '하';
            char hellFourthLetter = '세';
            System.out.println("韩语的你好是" + helloFirstLetter + helloSecondLetter + helloThirdLetter + hellFourthLetter);
        }
    }

程序运行结果

image

站长工具还提供了Unicode字符集转换工具,可以将指定的中文转换为对应的Unicode编码

image

也可以将指定的Unicode编码转换为中文

image

5.3.4 转义字符的使用

转义字符就是转变字符原有的含义

在日常开发中会使用到以下的这些转义字符

转义字符作用
‘\n’换行
‘\t’制表符
‘\’路径转义 表示\
‘’’转义单引号
‘"’转义双引号

CharacterESCVariable.java演示常用转义字符的使用

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 转义字符的使用
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/10 11:07
 * @since Java17
 */
public class CharacterESCVariable {
    public static void main(String[] args) {
        System.out.print("Hello");
        char newLine = '\n';
        //\n 换行
        System.out.print(newLine);
        System.out.println("World");
        // \t 制表符
        System.out.println("Hello\tWorld");

        // \表示 \
        String windowsPath = "D:\BaiduSyncdisk\project\github\awesome-java";
        System.out.println("windowsPath = " + windowsPath);

        String macPath = "/Users/liuguanglei/Documents/java/project/github/awesome-java";
        System.out.println("macPath = " + macPath);

        // \"表示 "
        System.out.println("\"跟光磊学Java从小白到架构师\"");
        // \' 表示'
        System.out.println("\'跟光磊学Java从小白到架构师\'");
    }
}

程序运行结果

image

需要特殊说明的是’\t’制表符,在Windows终端打印的时候把前面字符串的长度补齐到8或者是8的整数倍,最少补1个空格,最多补8个空格。

CharacterTab.java演示制表符的使用

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 制表符的使用
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/10 14:09
 * @since Java17
 */
public class CharacterTab {
    public static void main(String[] args) {
        //没有使用制表符演示数据
        System.out.println("姓名年龄");
        System.out.println("tom 28");
        //使用制表符演示数据
        System.out.println("姓名\t年龄");
        System.out.println("tom\t28");
    }
}

Windows终端程序运行结果

image

IntelliJ IDEA运行结果

image

5.3.5 字符类型与算术运算

char类型是可以进行算术运算的,此时char相当于一个整数,因为它都有对应的Unicode编码,Unicode编码兼容ASCII编码。

CharacterArithmeticOperator.java演示字符参与加法运算

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 字符参与算术运算
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/10 14:13
 * @since Java17
 */
public class CharacterArithmeticOperator {
    public static void main(String[] args) {
        int result = 'a' + 10;
        //因为字符a对应的unicode编码是97
        //97+10=107
        //因此 result = 107
        System.out.println("result = " + result);

        char ch = 'b' + 1;
        //因为字符b对应的unicode编码是99
        // 98+1=99
        //因此 (int) ch =99
        System.out.println("(int) ch = " + (int) ch);
        //99对应的字符是c
        //因此ch = c
        System.out.println(" ch = " + ch);
    }
}

程序运行结果

image

5.3.6 字符在内存中的存储

ASCII字符集使用ASCII字符编码存储字符,使用一个字节存储字符,ASCII字符编码二进制左边第一位是0

ASCII字符码点(编号)存储格式(二进制)
‘0’480011 0000
‘a’970110 0001
‘A’650100 0001

Unicode字符集常用的字符编码是UTF-8,UTF-8字符编码规定Unicode字符集的字符存储规则,它使用一至四个字节(可变长度)为每个字符编码

  • 128个US-ASCII字符,只需一个字节编码。

  • 拉丁文等字符,需要二个字节编码。

  • 大部分常用字(含中文)使用三个字节编码

  • 其他极少使用的Unicode辅助字符,使用四字节编码

UTF-8还规定Unicode字符集对应的二进制存储方式

字节数二进制存储方式说明
1个字节0xxx xxxx (ASCII码)第一个字节开头必须是0
2个字节110xxxx 10xxxxxx第一个字节开头必须是110,第二个字节开头必须是10
3个字节1110xxxx 10xxxxxx 10xxxxxx第一个字节开头必须是1110,第二个字节、第三个字节开头必须是10
4个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx第一个字节开头必须是11110,第二个字节、第三个字节、第四个字节开头必须是10

案例:中文字符’我’在内存中是如何存储

CharacterCodePointEncodingDecoding.java演示获取中文字符’我’在内存中二进制存储形式的过程

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

import java.nio.charset.Charset;
import java.util.Arrays;

/**
 * 中文字符'我'在内存中是如何存储
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/19 22:27
 * @since Java17
 */
public class CharacterCodePointEncodingDecoding {
    public static void main(String[] args) {

        // 1.获取字符'我'的码点,即Unicode字符集编号
        //定义一个字符数组存储字符我 因为获取码点的方法只接受字符数组作为参数
        char ch = '我';
        char[] chars = {ch};
        int codePoint = Character.codePointAt(chars, 0);
        //字符我的码点是25105
        System.out.println("字符" + ch + "的码点是" + codePoint);

        //2. 将码点转换为二进制形式
        String binaryString = Integer.toBinaryString(codePoint);
        //字符我的二进制补码是110 001000 010001
        System.out.println("字符" + ch + "的二进制补码是" + binaryString);

        //获取字符我的二进制补码简化写法
        // System.out.println("字符" + ch + "的二进制补码是" +Integer.toBinaryString(Character.codePointAt(new char[]{'我'}, 0)));


        //按照UTF-8字符编码的规则 中文占据3个字节
        //第一个字节开头必须是1110,第二个字节、第三个字节开头必须是10
        //因此第一个字节是11100110 第二个字节是10001000 第三个字节是10010001

        //字符我在内存中的存储形式是11100110 10001000 10010001

        //3.验证结果是否正确
        //首先获取当前平台默认字符编码
        System.out.println("当前平台默认的字符编码是 " + Charset.defaultCharset());
        //然后获取中文字符'我'的每个字节(中文占据3个字节)
        String str = "我";
        // getBytes() 使用平台默认的字符编码将字符串编码为一系列字节,将结果存储到新的字节数组中
        byte[] bytes = str.getBytes();
        //将之前推断的3个字节补码转换成原码、十进制
        
        //第一个字节11100110换算成原码并转换成十进制
        //补码:1110 0110
        //反码:1110 0101
        //原码:1001 1010
        //转换成十进制:-26

        //第二个字节10001000换算成原码转换成十进制
        //补码:1000 1000
        //反码:1000 0111
        //原码:1111 1000
        //转换成十进制:-120

        //第三个字节10010001换成原码转换成十进制
        //补码:1001 0001
        //反码:1001 0000
        //原码:1110 1111
        //转换成十进制:-111

        // 输出结果:字符'我'使用平台默认的字符编码将字符串编码为一系列字节分别是-26, -120, -111
        //刚好和推断的三个字节从补码转换成原码后十进制数值一一对应
        //因此推断结果正确
        System.out.println("字符'我'使用平台默认的字符编码将字符串编码为一系列字节" + Arrays.toString(bytes));


    }
}

程序运行结果

image

5.4 布尔类型

5.4.1 布尔类型介绍

布尔类型是用于描述真假信息的

在Java语言中使用boolean表示布尔类型,布尔类型的字面值取值只能是true或者false,而不能使用0或者非0的整数代替false和true,这点和C语言不同。

需要注意的是Java 虚拟机中没有任何供 boolean 值专用的字节码指令, Java 语言 表达所操作的boolean 值,在编译之后都使用 Java 虚拟机中的 int类 型来代替: true 用 1 表示, false 用 0 表示,因此boolean在内存中分配4个字节

布尔类型主要在程序流程控制语句中使用,例如if/else 语句、while语句。

5.4.2 布尔类型使用

BooleanVariable.java演示布尔类型使用,以及在条件判断语句和循环的使用案例

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 布尔类型使用
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/10 14:16
 * @since Java17
 */
public class BooleanVariable {
    public static void main(String[] args) {
        /***********************boolean类型的变量和字面量***********************/
        //boolean类型的字面值只能是true或者false
        //boolean类型的变量只能存储true或者false
        boolean flag = true;
        System.out.println("flag = " + flag);
        flag = true;
        System.out.println("flag = " + flag);

        // 不能将非布尔类型的字面值、变量赋值给布尔类型的变量
        //flag = 1;

        //布尔类型使用场景


        //1.布尔变量在if/else条件判断语句中的使用
        //是否成年
        boolean isGrowUp = false;
        if (isGrowUp) { //等价于isGrowUp==true 在Java中=表示赋值,==表示是否相等
            System.out.println("恭喜你已经成年了,你就可以去网咖上网打游戏了");
        } else {
            System.out.println("你还没有成年,你不能去网咖上网打游戏");
        }

        //2. 布尔类型字面值在while语句中的使用
        while (true) {
            System.out.println("我是一个死循环");
        }

    }
}

程序运行结果

说明:程序最后会一直打印我是一个死循环,除非点击停止按钮手动停止程序

image

5.5 基本数据类型转换

5.5.1 基本数据类型转换介绍

在 Java 程序中,不同的基本数据类型(只有 7 种,不包含 boolean 类型)变量的值经常需要进行相互转换,转换的方式有两种: 自动类型提升强制类型转换

5.5.2 基本数据类型自动类型转换

由于数据类型不一样不能进行计算,需要转换成一样类型的才能进行计算,而当Java程序在进行运算的时候,取值范围小的数据类型可以自动转换成取值范围大的数据类型,这个就是自动类型转换,也叫做隐式转换或者是自动类型提升。

自动类型转换可以在一定的程度上避免数据在运算的时候超过数据类型的极限而造成程序的错误

基本数据类型自动类型转换的转换规则:将取值范围小的类型自动提升为取值范围大的类型

image

PrimitiveTypeAutoConversionAssignmentOperator.java演示了7种Java基本数据类型的自动类型转换

 package net.ittimeline.java.core.foundational.syntax.variable.type.primitive.conversion;
    
    /**
     * 7种基本数据类型的自动类型转换-赋值运算
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/10 16:51
     * @since Java17
     */
    public class PrimitiveTypeAutoConversionAssignmentOperator {
        public static void main(String[] args) {
    
            //自动类型转换规则:将取值范围小(或容量小)的类型自动提升为取值范围大(或容量大)的类型
    
            /*********************byte(赋值运算)自动转换为short*********************/
            byte byteVar = Byte.MAX_VALUE;
            short shortVar = byteVar;
            System.out.println("shortVar = " + shortVar);
    
            /*********************short(赋值运算)自动转换为int*********************/
            shortVar = Short.MAX_VALUE;
            int intVar = shortVar;
            System.out.println("intVar = " + intVar);
    
            /*********************char(赋值运算)自动转换为int*********************/
    
            char letterA = 'a';
            //char自动转换成int
            int intRes = letterA;
            //字母a对应的编码值是97
            System.out.println("intRes = " + intRes);
    
            char upperA = 'A';
            intRes = upperA;
            //字母A对应的编码值是65
            System.out.println("intRes = " + intRes);
            int number = 'c';
            System.out.println("number = " + number);
    
            /*********************int(赋值运算)自动转换为long*********************/
            intVar = Integer.MAX_VALUE;
            long longVar = intVar;
            System.out.println("longVar = " + longVar);
    
    
            /*********************long(赋值运算)自动转换为float*********************/
            float longMaxValue = Long.MAX_VALUE;
            System.out.println("longMaxValue = " + longMaxValue);
    
    
            /*********************float(赋值运算)自动转换为double*********************/
            double floatMaxValue = Float.MAX_VALUE;
            System.out.println("floatMaxValue = " + floatMaxValue);
    
    
        }
    }
    

程序运行结果

image

需要注意的是byte、short、char三个类型的变量之间进行运算,结果为int类型

  package net.ittimeline.java.core.foundational.syntax.variable.type.primitive.conversion;
    
    /**
     * 7种基本数据类型的自动类型转换-算术运算
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/10 19:57
     * @since Java17
     */
    public class PrimitiveTypeAutoConversionArithmeticOperator {
        public static void main(String[] args) {
            byte byteVar = 12;
            System.out.println("byteVar = " + byteVar);
            short shortVar = 12;
            System.out.println("shortVar = " + shortVar);
            /*************byte、char、short三个类型的变量之间进行运算,运算结果类型是int*************/
            int intResult = byteVar + byteVar;
            System.out.println("byte和byte运算 intResult = " + intResult);
    
            intResult = byteVar + shortVar;
            System.out.println("byte和short运算 intResult = " + intResult);
    
            intResult = shortVar + shortVar;
            System.out.println("short和short运算 intResult = " + intResult);
            char charVar = 'a';
            //char参与算术运算会使用字符对应的编码值参与运算
            //字符a的编码值是97
            intResult = byteVar + charVar;
            System.out.println("byte和char运算 intResult = " + intResult);
    
            //整数字面量1默认是int类型 因此结果是int类型
            intResult = byteVar + 1;
            System.out.println("byte类型和整数字面量进行加法运算 intResult = " + intResult);
    
            //小数字面量3.14默认是double类型,因此结果是double类型
            double doubleResult = byteVar + 3.14;
            System.out.println("byte类型和浮点类型字面量进行加法运算 doubleResult = " + doubleResult);
            
            //为什么标识符不能是数字开头? 因为42行的变量赋值 123L无法区分是标识符还是数字
            /*
            int 123L=100;
            long value=123L;
            */
        }
    }

程序运行结果

image

5.5.3 基本数据类型强制类型转换

将一个取值范围大的(例如double)数值赋值给取值范围小的(例如int)变量是不允许直接赋值的,如果一定要这么做就需要使用强制类型转换

int value =(double)567.88;

强制类型转换是自动类型转换的逆运算,也就是将取值范围大的数据类型强制转换为取值范围较小的数据类型。

强制类型转换的语法格式:取值范围较小的数据类型 变量名 = (取值范围较小的数据类型) 取值范围较大的变量或者是字面量

PrimitiveTypeNarrowConversion.java演示基本数据类型强制类型转换的使用

 package net.ittimeline.java.core.foundational.syntax.variable.type.primitive.conversion;
    
    /**
     * 基本数据类型的强制类型转换
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/10 20:19
     * @since Java17
     */
    public class PrimitiveTypeNarrowConversion {
        public static void main(String[] args) {
            //自动类型提升
            double doubleVar = 12;
            System.out.println("int自动转换为double doubleVar = " + doubleVar);
            //强制类型转换语法格式:取值范围较小的数据类型 变量名 = (取值范围较小的数据类型) 取值范围较大的变量或者是字面量
    
            /*************************1. double强制转换为int*************************/
            double dbl = 3.14;
            //编译错误 不能直接将double类型的变量赋值给int
            //int intVar = dbl;
    
            int intVar = (int) dbl;
            System.out.println("double强制转换为int " + intVar);
    
            double salary = 300000.00;
            int intSalary = (int) salary;
            System.out.println("double强制转换为int intSalary = " + intSalary);
    
            /*************************2. long强制转换为byte*************************/
            long longVar = 123;
            //编译失败
            //byte byteVar=longVar;
            byte byteVar = (byte) longVar;
            System.out.println("long强制转换为byte byteVar = " + byteVar);
    
    
        }
    }
    

程序运行结果

image

强制类型转换可能会发生精度损失

PrimitiveTypeNarrowConversionPrecision.java演示基本数据类型进行强制类型转换的精度损失问题

  package net.ittimeline.java.core.foundational.syntax.variable.type.primitive.conversion;
    
    /**
     * 基本数据类型强制类型转换的精度损失问题
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/12 19:59
     * @since Java17
     */
    public class PrimitiveTypeNarrowConversionPrecision {
        public static void main(String[] args) {
            //double强制转换为int的精度损失问题
            double doubleVar = 5.8;
            System.out.println("double强制转换为int之前 doubleVar = " + doubleVar);
    
            //double强制转换为int后小数部分会被舍弃,会有精度损失
            int intVar = (int) doubleVar;
            System.out.println("double强制转换为int之后 intVar = " + intVar);
    
    
            //int强制转换为byte的精度损失问题
            int intValue = 128;
            System.out.println("int强制转换为byte之前 intValue = " + intValue);
            //128超出byte的表示范围,因此结果为-128,因为底层二进制补码是1000 0000
            byte byteVar = (byte) intValue;
            System.out.println("int强制转换为byte之后 byteVar = " + byteVar);
        }
    }

程序运行结果

image

6. Java API

6.1 Java API介绍

在学习Java语言的基础语法(注释、变量、数据类型、运算符、程序流程控制、数组)以及面向对象编程以后,就会集中大部分精力学习日常开发中经常使用的Java API(类、接口、枚举、注解、记录)

而在之前我们已经使用过一些Java的API(类),例如java.lang.System、java.lang.Long、java.lang.Double、java.lang.String等等

image

在IntelliJ IDEA中可以使用快捷键Ctrl+N/Command+O搜索指定的类,例如搜索System类

image

System类源文件>System.java

image

Java API的源文件(.java结尾的文件)位于JDK安装目录src.zip文件中,不同的JDK版本src.zip所在的目录是不相同的

Java8的src.zip位于C:\Program Files\Java\jdk-1.8目录下

image

Java17的src.zip位于C:\Program Files\Java\jdk-17\lib目录下

image

之前使用的java.lang.Double、java.lang.Long、java.lang.String、java.lang.System等等,这些类对应的源文件(.java结尾的文件)都是在src.zip文件中

image

但是程序运行的时候使用的字节码文件(.class结尾的文件)

不同Java版本的字节码文件所在的位置不同

Java17位于目录下C:\Program Files\Java\jdk-17.0.5\jmods,这些文件可以使用WinRAR打开

image

例如java.base.jmod的classes\java\lang目录下就有java.lang.Double、java.lang.Long、java.lang.String、java.lang.System对应的字节码文件

image

image

Java8的字节码文件位于C:\Program Files\Java\jdk-1.8\jre\lib目录下的rt.jar中,

image

该文件也可以使用WinRAR打开

image

在java\lang目录下就有java.lang.Double、java.lang.Long、java.lang.String、java.lang.System对应的字节码文件

image

image

以后我们Java项目还会依赖许多第三方框架(MyBatis、Spring Framework、SpringBoot),这些第三方框架就是由许多字节码文件打成的jar包

image

在开发Java项目的时候,我们会使用到如下列表(包名)的API,每个包下都有许多类、接口、枚举、注解

  • java.io IO操作

  • java.lang 语言基础、反射

  • java.math 数学运算

  • java.net 网络编程

  • java.nio 异步IO编程

  • java.text 文本格式化

  • java.time 日期/时间

  • java.util 集合、并发、函数式编程、流式编程、正则表达式、日志

image

  • java.sql 数据库

image

学习Java API有两种方式

  1. 阅读Java API文档,关注Java API的使用

  2. 阅读Java API源码,关注Java API的使用和源码实现

6.2 Java API文档

6.2.1 Java API文档介绍

Java API文档是采用JDK提供的javadoc通过提取Java源码中的文档注释相关内容生成的网页文档,通过阅读Java API文档可以快速掌握Java API的使用。

image

因为Java8的API文档不支持搜索,所以不建议使用Java8的API文档

建议大家直接使用Java11或者是Java17的API文档,因为这两个版本支持搜索类、方法等等,而且Java11和Java17会向下兼容Java8

在Java17的官方文档首页点击Specifications的API Documentation

image

就可以访问Java17的API文档

API文档首页是一个概述页面,该页面列出了Java的全部模块,这些模块可以通过 All Modules进行查看,也可以通过分类进行查看。

Java将这些模块分为三类

  1. JavaSE:该模块主要包含Java SE的各种类

  2. JDK:该模块主要包含JDK的各种工具类,这部分API在不同的JDK实现上可能存在差异

  3. Other Modules:包含其他功能的API

image

Java17 API文档首页右上角有搜索框,可以用于搜索类、接口、注解、枚举、以及类中的成员变量、常量、成员方法、构造器

image

Java17 API文档搜索类

搜索String类:输入String,然后选择java.lang.String,因为String是位于java.lang包中

image

就会跳转到String的API文档

image

Java17 API文档搜索成员方法

搜索String的charAt()方法:直接搜索charAt(),然后选择String.charAt()

image

就可以看到charAt()方法的文档注释说明

image

Java17 API文档搜索构造器

搜索String的String(char[])构造方法:直接搜索String(char[]),然后选择java.lang.String.String(char[])

image

6.2.2 Java API文档内容说明

Java17 API文档包含了类的说明、字段摘要、构造方法摘要、方法摘要

String类的定义和说明

image

String类字段摘要

image

String类的构造方法摘要

image

String类的(部分)方法摘要

image

我们在学习Java API的时候重点关注构造方法和方法的使用

  • 构造方法是如何创建对象,创建对象的语法是类名 对象名 = new 类名(实际参数列表)

  • 方法是完成对应的功能,通过对象名.方法名(实际参数列表)调用

在Java API文档中可以点击方法摘要的某个方法,跳转到该方法的详细说明

例如点击charAt()方法

image

就可以跳转到该方法的详细说明:包含方法签名和方法文档注释说明

image

6.3 IntelliJ IDEA中查看Java API源码

除了可以查看Java API文档学习Java API使用,还可以通过IntelliJ IDEA查看Java API源码学习Java API的使用

需求:在IntelliJ IDEA查看String类源码学习String API

  1. 使用快捷键Ctrl+N/Command+O打开搜索Classes窗口

不过Scope默认是Project Files,也就是默认的作用域是搜索项目中的内容

image

需要将Scope从Project Files改成All Places

image

image

  1. 搜索String

①在搜索框中输入String ②选择String of java.lang

image

然后就可以看到String.java的源代码文件

image

  1. 点击Structure查看该类的结构,即类的成员(成员变量、常量、成员方法、构造器)

image

image

  1. 选择要查看的指定成员

在Structure窗口

①使用Ctrl+f查找指定的成员,例如查找charAt(int)方法

②选择charAt(int)方法

image

IntelliJ IDEA编辑器会自动跳转到charAt(int)方法

image

如果你是首次在IntelilJ IDEA中打开Java API的源代码(例如String.java),那么默认情况会启用Reader Mode

image

点击Reader Mode左边的x可以退出阅读模式

image

image

点击书本图标可以进入阅读模式

image

image

JavaAPI文档就是提取Java API源码中的文档注释生成的网页文档

image

在查找Java API的成员时除了可以在Structure窗口使用Ctrl+f查找,还可以在编辑器使用Cltr+F12/Command+F12列出Java API的所有成员

image

然后再输入指定的成员名查找即可

① 输入Java API查找的成员

②选择Java API查找的成员

image

编辑器就会定位到Java API指定的成员

image

7. String

7.1 String类介绍

由于现实生活中很少有数据使用字符描述,因此在以后的项目开发中更多的是使用多个字符拼接的字符串,字符串的字面量使用一对双引号(“”)包含起来,用于描述各种信息,例如姓名、家庭地址、籍贯等等。

在Java中使用java.lang.String类来表示字符串类型,String不属于八种基本数据类型,属于引用数据类型的类(class)。

image

String是在项目开发中使用最多的数据类型,没有之一。

字符串字面量使用一对双引号(“”)包含起来的,例如"HelloWorld",“跟光磊学Java从小白到架构师”

7.2 String变量

StringVariable.java演示字符串变量的定义和使用

package net.ittimeline.java.core.foundational.syntax.variable.type.reference.string;

/**
 * String类型变量的使用
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/12 20:10
 * @since Java17
 */
public class StringVariable {
    public static void main(String[] args) {
        /*********************字符串可以包含0到多个字符*********************/

        //定义一个String类型的变量empty,包含0个字符,也就是空字符串
        String empty = "";
        System.out.println('[' + empty + ']');

        //定义一个String类型的变量blank,包含一个空格
        String blank = " ";
        System.out.println("Hello" + blank + "world");

        /*********************字符串变量的定义和使用************************/
        //字符串变量的定义
        String name = "tony";
        String nativePlace = "湖北";
        String address = "上海市";
        //字符串变量的使用
        System.out.println("个人信息如下");
        System.out.println("姓名:" + name);
        System.out.println("籍贯:" + nativePlace);
        System.out.println("地址:" + address);
        //字符字面量必须有且只能有一个字符
       // char ch ='';


    }
}

程序运行结果

image

7.3 字符串拼接

String可以和八种基本数据类型进行运算,但是只能用加号(+)进行连接运算实现字符串拼接,拼接之后的结果还是String类型。

StringConcat.java演示字符串连接的使用

 package net.ittimeline.java.core.foundational.syntax.variable.type.reference;
    
    /**
     * 字符串连接的使用
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/12 20:45
     * @since Java17
     */
    public class StringConcat {
        public static void main(String[] args) {
            /*********************String和8种基本数据类型连接******************************/
    
            int number = 101;
            String str = "编号:";
            //字符串和整数连接
            String numberStr = str + number;
            System.out.println("numberStr = " + numberStr);
            //字符串和字符、整数的连接
            //如何区分加号(+)表示加法还是字符串连接
            number = 100;
            char ch = 'A';
            str = "Hi";
            //第一个+表示加法运算
            //第二个+表示字符串连接
            //最终的运算结果是165Hi
            System.out.println("number+ch+str = " + (number + ch + str));
    
            //第一个+表示字符串连接
            // 第二个+表示字符串连接
            // 最终的运算结果是HiA100
            System.out.println("str+ch+number = " + (str + ch + number));
    
            //使用字符串连接个人信息:
            String name = "tony";
            int age = 30;
            char gender = '男';
            double height = 175.00;
            double weight = 150.00;
            boolean isMarried = false;
            System.out.println("个人信息: 姓名:" + name + "年龄:" + age + "性别:" + gender + "身高:" + height + "体重:" + weight + "是否已婚:" + isMarried);
            /*********************连接图案:******************************/
            //连接如下图案:*   *   *
            //有如下方法
            System.out.println("*   *   *");
            System.out.println("*" + "\t" + "*" + "\t*");
            System.out.println('*' + "\t" + "*" + "\t*");
            //只要打印语句中有一个字符串 最终的结果就是字符串
            System.out.println("*" + '\t' + "*" + "\t*");
            //下面打印输出的结果不是我们要的 因为操作数都是字符类型,最终运行的结果是int
            System.out.println('*' + '\t' + '*' + '\t' + '*');
    
        }
    }
    

程序运行结果

image

Q:加号(+)什么时候表示字符串拼接,还是加法运算?

A:加号(+)+左右两边只要有字符串变量或者是字符串字面量就是字符串拼接,+左右两边有7种数值类型的数据就表示加法

7.4 String和基本数据类型相互转换

  1. 基本数据类型转换为String类型:将基本类型的值+空字符串(“”)

PrimitiveType2String.java演示常用的六种基本数据类型(byte、char、int、long、double、boolean)转换为字符串

  package net.ittimeline.java.core.foundational.syntax.variable.type.reference.string;
    
    /**
     * 基本数据类型转换为String
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/12 21:21
     * @since Java17
     */
    public class PrimitiveType2String {
        public static void main(String[] args) {
    
            /***********************常用的六种基本数据类型转换为String********************************/
            //基本数据类型转String:将基本类型的值+""即可
            byte byteVar = 127;
            String byteVarStr = byteVar + "";
            System.out.println("将byte转换为String byteVarStr = " + byteVarStr);
    
            char chVar = 'a';
            String chVarStr = chVar + "";
            System.out.println("将char转换为String chVarStr = " + chVarStr);
            
            int intVar = 100_0000;
            String intVarStr = intVar + "";
            System.out.println("将int转换为String intVarStr = " + intVarStr);
    
            long longVar = 100_0000_0000L;
            String longVarStr = longVar + "";
            System.out.println("将long转换为String longVarStr = " + longVarStr);
    
    
            double doubleVar = 8.88;
            String doubleVarStr = doubleVar + "";
            System.out.println("将double转换为String doubleVarStr = " + doubleVarStr);
    
            boolean booleanVar = true;
            String booleanStr = booleanVar + "";
            System.out.println("将boolean转换为String booleanStr = " + booleanStr);
    
    
        }
    }
    

程序运行结果

image

  1. String转换为基本数据类型

我们需要了解八种基本数据类型对应的包装类

基本数据类型包装类
byteByte
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean
  • byte可以通过调用包装类Byte的public static byte parseByte(String s) throws NumberFormatException 方法实现将byte转换为String

  • char可以通过调用String对象的public char charAt(int index)方法获取指定位置的字符实现将字符串转换为字符

  • int可以通过调用包装类Integer的public static byte parseInt(String s) throws NumberFormatException 方法实现将int转换为String

  • long可以通过调用包装类Long的public static byte parseLong(String s) throws NumberFormatException 方法实现将long转换为String

  • double可以通过调用包装类Double的public static byte parseDouble(String s) throws NumberFormatException 方法实现将double转换为String

  • boolean可以通过调用包装类Integer的public static byte parseBoolean(String s) throws NumberFormatException 方法实现将boolean转换为String

String2PrimitiveType.java演示字符串转换为常用的6种基本数据类型

 package net.ittimeline.java.core.foundational.syntax.variable.type.reference.string;
    
    /**
     * String转换为基本数据类型
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/12 21:20
     * @since Java17
     */
    public class String2PrimitiveType {
        public static void main(String[] args) {
            /**********************字符串转换为常用的六种基本数据类型*****************************/
            //1.字符串转换为byte
            String byteVarStr = "20";
            //调用byte对应的包装类Byte的parseByte()方法将字符串20转换为byte类型
            byte byteVar = Byte.parseByte(byteVarStr);
            System.out.println("1.字符串转换为byte byteVar = " + byteVar);
    
            // 2.字符串转换为char
            String charVarStr = "a";
            //调用字符串对象的charAt()方法获取字符串的第一个字符
            char charVar = charVarStr.charAt(0);
            System.out.println("2.字符串转换为char charVar = " + charVar);
    
            // 3.字符串转换为int
            String intVarStr = "1000000";
            int intVar = Integer.parseInt(intVarStr);
            System.out.println("3.字符串转换为int intVar = " + intVar);
    
    
            //4.字符串转换为long
            String longVarStr = "10000000000";
            long longVar = Long.parseLong(longVarStr);
            System.out.println("4.字符串转换为long longVar = " + longVar);
    
            // 5.字符串转换为double
            String doubleVarStr = "3.1415926";
            double doubleVar = Double.parseDouble(doubleVarStr);
            System.out.println("5.字符串转换为double doubleVar = " + doubleVar);
    
            // 6.字符转转换为boolean
            String booleanVarStr = "true";
            boolean booleanVar = Boolean.parseBoolean(booleanVarStr);
            System.out.println("6.字符转转换为boolean booleanVar = " + booleanVar);
    
        }
    }

程序运行结果

image

在调用包装类的parseXXX()方法将字符串转换为基本数据类型时需要注意

如果是转换为数值类型,那么字符串必须是数值,并且在数值类型的取值范围内,否则就会出现NumberFormatException

image

String2PrimitiveTypeNumberFormatException.java演示字符串转换为基本数据类型可能会出现NumberFormatException的情况

 package net.ittimeline.java.core.foundational.syntax.variable.type.reference.string;
    
    /**
     * 字符串转换为基本数据类型可能会出现NumberFormatException的情况
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/13 9:28
     * @since Java17
     */
    public class String2PrimitiveTypeNumberFormatException {
        public static void main(String[] args) {
            //字符串转换为long 正常转换
            String longVarStr1 = "10000000000";
            long longVar1 = Long.parseLong(longVarStr1);
            System.out.println("字符串转换为long longVar1 = " + longVar1);
    
            //字符串转换为基本数据类型,如果是转换为数值类型,那么字符串必须是数值,并且在数值类型的取值范围内,否则就会出现NumberFormatException
    
            //字符串转换为基本数据类型可能会出现NumberFormatException的情况1
            /*
            
            //字符串100_0000_0000不全是数值,还包括下划线(_)
            String longVarStr2 = "100_0000_0000";
            //因此在转换为基本数据类型long时会发生NumberFormatException异常
            long longVar2 = Long.parseLong(longVarStr2);
            System.out.println("字符串转换为long NumberFormatException longVar2 = " + longVar2);
            
            */
            
            
            //字符串转换为基本数据类型可能会出现NumberFormatException的情况2
            /*
            
            String byteVarStr1 = "127";
            byte byteVar1 = Byte.parseByte(byteVarStr1);
            System.out.println("byteVar1 = " + byteVar1);
    
            //字符串"128"虽然全是数字,但是超过了byte的取值范围
            String byteVarStr2 = "128";
            //因此在转换为基本数据类型byte时会发生NumberFormatException异常
            byte byteVar2 = Byte.parseByte(byteVarStr2);
            System.out.println("byteVar2 = " + byteVar2);
             */
        }
    }
    

程序运行结果

情况1

想要获取情况1的运行结果,需要将20行和28行的多行注释删除

image

情况2

想要获取情况2的运行结果,需要将32行和43行的多行注释删除

image

8. 键盘输入

8.1 Scanner类介绍

Scanner类是用于读取从键盘输入不同类型(基本数据类型、String)的数据

具体步骤如下

  1. 导包

如果我们使用的API不是位于java.lang包,就必须要使用import语句导包

导包的语法是import 包名.类名;

由于Scanner类是位于java.util包

image

在使用Scanner之前需要使用import语句导包

import java.util.Scanner;

导包语句必须位于包语句和类定义的中间

image

  1. 创建Scanner类型的对象

System.in表示标准输入,也就是键盘

Scanner对象可以读取用户从键盘输入的数据

Scanner scanner =new Scanner(System.in);
  1. 调用Scanner类的相关方法来获取指定类型的数据
*   public byte nextByte() 读取键盘输入的byte类型的数据
    
*   public int nextInt() 读取键盘输入的int类型数据
    
*   public int nextLong() 读取键盘输入的long类型数据
    
*   public double nextDouble() 读取键盘输入的double类型数据
    
*   public double nextBoolean() 读取键盘输入的boolean类型数据
    
*   public String next()读取键盘输入的字符串数据

需要注意的是Scanner没有提供读取键盘输入的char类型数据,需要通过public String next()方法读取键盘输入的字符串数据,然后再调用字符串对象的chartAt(0)获取第一个字符,从而实现读取键盘从输入的char类型数据。

  1. 释放资源
scanner.close();

8.2 Scanner使用

需求1:读取用户从键盘输入的整数,并打印输出

package net.ittimeline.java.core.foundational.syntax.variable.type.reference.scanner;

import java.util.Scanner;

/**
 * 需求1:读取用户从键盘输入的整数,并打印输出
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/13 8:50
 * @since Java17
 */
public class ScannerIntTest {

    public static void main(String[] args) {
        //创建Scanner对象
        //System.in 标准输入 也就是键盘输入
        //Scanner对象可以扫描用户从键盘输入的数据
        Scanner scanner = new Scanner(System.in);

        //提示用户从键盘输入一个整数
        System.out.println("请输入一个整数");

        //读取用户从键盘输入的整数并赋值给number变量
        int number = scanner.nextInt();
        //输出用户从键盘输入的整数
        System.out.println("你从键盘输入的整数是" + number);
        
        scanner.close();
    }
}

程序运行结果

image

需要说明的是当程序执行到 System.out.println(“请输入一个整数”);时会阻塞,等待用户输入数据

image

需求2:读取用户从键盘输入的两个整数并求和

ScannerIntSumTest.java演示需求2:读取用户从键盘输入的两个整数并求和的实现过程

package net.ittimeline.java.core.foundational.syntax.variable.type.reference.scanner;

import java.util.Scanner;

/**
 * 需求2:读取用户从键盘输入的两个整数并求和
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/13 9:11
 * @since Java17
 */
public class ScannerIntSumTest {
    public static void main(String[] args) {
        //创建Scanner对象
        //System.in 标准输入 也就是键盘输入
        //Scanner对象可以扫描用户从键盘输入的数据
        Scanner scanner = new Scanner(System.in); //② 创建Scanner对象

        //提示用户从键盘输入一个整数
        System.out.println("请输入第一个整数");

        //读取用户从键盘输入的整数并赋值给number变量
        int firstNumber = scanner.nextInt(); //③调用Scanner对象的nextInt()方法获取用户从键盘输入的整数

        System.out.println("请输入第二个整数");
        int secondNumber = scanner.nextInt();

        int sum = firstNumber + secondNumber;

        //输出用户从键盘输入的整数
        System.out.println("两个整数的和是" + sum);

        scanner.close();//④释放资源
    }
}

程序运行结果

image

需求3:读取用户从键盘输入的交友网注册信息并输出

  package net.ittimeline.java.core.foundational.syntax.variable.type.reference.scanner;
    
    import java.util.Scanner;
    
    /**
     * 需求3:读取用户从键盘输入的交友网注册信息并打印输出
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/13 9:15
     * @since Java17
     */
    public class ScannerUserInfoRegisterTest {
        public static void main(String[] args) {
    
            System.out.println("欢迎访问交友网,请先注册。。。");
            //创建Scanner对象
            //System.in 标准输入 也就是键盘输入
            //Scanner对象可以扫描用户从键盘输入的数据
            Scanner scanner = new Scanner(System.in);
    
            System.out.println("请输入你的姓名");
            String name = scanner.next();
    
            System.out.println("请输入你的年龄");
            int age = scanner.nextInt();
    
            System.out.println("请输入你的性别(男/女)");
            String genderStr = scanner.next();
            char gender = genderStr.charAt(0);
    
            System.out.println("请输入你的身高");
            double height = scanner.nextDouble();
    
            System.out.println("请输入你的体重");
            double weight = scanner.nextDouble();
    
            System.out.println("请输入你的婚姻状况(true:已婚\false:未婚)");
            boolean isMarried = scanner.nextBoolean();
    
            System.out.println("用户注册成功");
            String userInfo = "用户姓名:" + name + " 年龄" + age + " 性别:" + gender + " 身高:" + height + " 体重:" + weight + " 婚姻状况:" + isMarried;
            System.out.println("交友网用户注册信息:" + userInfo);
    
            //关闭资源
            scanner.close();
    
    
        }
    }

程序运行结果

image

8.3 Scanner使用注意事项

Scanner类在扫描数据的时候应该要注意输入的数据类型和Scanner扫描的数据类型保持一致,如果不一致会引发InputMismatchException异常

ScannerInputMismatchException.java演示InputMismatchException异常

  package net.ittimeline.java.core.foundational.syntax.variable.type.reference.scanner;
    
    import java.util.Scanner;
    
    /**
     * Scanner使用注意事项
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/13 9:23
     * @since Java17
     */
    public class ScannerInputMismatchException {
    
        public static void main(String[] args) {
            //创建Scanner对象
            //System.in 标准输入 也就是键盘输入
            //Scanner对象可以扫描用户从键盘输入的数据
            Scanner scanner = new Scanner(System.in);
    
            System.out.println("请输入一个整数");
            int number = scanner.nextInt();
            System.out.println("你输入的整数是" + number);
            //关闭资源
            scanner.close();
        }
    }
    

程序运行结果

程序中提示用户从键盘输入一个整数,但是用户实际上输入的是一个小数,因此在使用Scanner对象调用public int nextInt()方法时发生了InputMismatchException异常

image

9. 格式化输出

9.1 格式化输出介绍

Java在PrintStream类中提供了public PrintStream printf(String format, Object … args)方法用于实现格式化输出,其中第一个参数是在格式字符串的语法中描述的格式字符串,第二个是格式字符串中的格式说明符引用的参数。

Q:如何调用printf(String format, Object … args)方法

A:System持有PrintStream类型的静态属性out,可以通过System.out获取PrintStream对象,然后再调用PrintStream对象的printf(String format, Object … args)方法即可

image

在使用printf(String format, Object … args)方法实现格式化输出之前需要先了解一些格式化符号。

格式化符号说明

格式化符号数据类型输出
%d整数 (byte, short, int, long, bigint)十进制整数
%o整数(byte, short, int, long, bigint)八进制
%x整数(byte, short, int, long, bigint)十六进制字符串
%f浮点数十进制数字
%e浮点数科学计数法中的十进制数
%g浮点数十进制数,可能采用科学记数法,具体取决于精度和值。
%c字符Unicode字符
%b任意类型“true” if non-null, “false” if null
%s任意类型字符串

9.2 格式化输出使用

FormatOutputPrimitiveType.java演示基本数据类型的格式化输出

package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;

/**
 * 基本数据类型的格式化输出
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/15 9:15
 * @since Java17
 */
public class FormatOutputPrimitiveType {
    public static void main(String[] args) {

        //1. 整数常用格式
        int age = 29;
        System.out.println("我今年" + age + "岁");
        //格式化输出不同进制的整数
        //%d 十进制格式
        System.out.printf("我今年%d岁\n", age);
        int number = 100;
        //System.out.println()默认是十进制输出
        System.out.println("number = " + number);
        //%o 八进制格式
        //%x 十六进制格式
        System.out.printf("100八进制表现形式是%o\n", number);
        System.out.printf("100十六进制表现形式是%x\n", number);


        //2. 浮点数(小数)常用格式
        //格式化输出浮点数
        double height = 180.00;
        System.out.println("我的身高是" + height + "厘米");
        //%f表示浮点数格式  %.2f 浮点数格式,小数点后保留2位
        System.out.printf("我的身高是%.2f厘米\n", height);

        double doubleValue = 100_0000.00;
        System.out.println("doubleValue = " + doubleValue);
        System.out.printf("doubleValue使用科学计数法表示为%e\n", doubleValue);


        //格式化输出字符
        //%c表示字符格式
        char ch = 'a';
        System.out.println(ch + "是第一个字符");
        System.out.printf("%c是第一个字符\n", ch);


        //格式化输出布尔
        //%b表示布尔格氏
        boolean flag = false;
        System.out.println("flag = " + flag);
        System.out.printf("flag = %b\n", flag);


    }
}

程序运行结果

image

FormatOutputPersonalInfoTest.java演示格式化输出个人信息

  package net.ittimeline.java.core.foundational.syntax.variable.type.primitive;
    
    /**
     * 格式化输出个人信息
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/13 10:48
     * @since Java17
     */
    public class FormatOutputPersonalInfoTest {
        public static void main(String[] args) {
            String name = "tony";
            int age = 24;
            double height = 185.00;
            double weight = 130.00;
            double salary = 50_0000.00;
            char gender = '男';
            boolean isMarried = false;
    
            System.out.println("没有使用格式化输出 显示个人信息");
            System.out.println("姓名:" + name + " 年龄:" + age + " 体重:" + weight + " 身高:" + height + " 年收入:" + salary + " 性别:" + gender + " 婚姻状况:" + isMarried);
            
            //格式化输出用户从键盘输入的用户信息
            // %s表示按照该字符串解析
            // %d表示按照整数解析
            //%.2f 表示按照小数解析,小数点后保留2位
            //%c 按照字符解析
            //%b 按照布尔类型解析
            System.out.println("使用格式化输出 显示个人信息");
            System.out.printf("姓名:%s 年龄:%d 体重:%.2f " +
                    "身高:%.1f 年收入:%.2f 性别:%c 婚姻状况:%b ", name, age, weight, height, salary, gender, isMarried);
        }
    }

程序运行结果

image

10. 变量和数据类型综合案例

10.1 使用变量统计统计公交车到终点站时车上的人数

  • 一开始没有乘客

  • 第一站上去1位乘客

  • 第二站上去3位乘客,下来1位乘客

  • 第三站上去4位乘客,下来2位乘客

  • 第四站下来1位乘客

  • 第五站上去一位乘客

  • 统计终点站(第五站)车上的乘客人数

package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 变量案例1:统计公交车到终点站时车上的人数
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/13 10:16
 * @since Java17
 */
public class VariableExample1Statistics {
    public static void main(String[] args) {
        //一开始没有乘客
        int count = 0;

        //第一站:上去1位乘客
        //将count加1的结果赋值给count
        count = count + 1;
        System.out.println("第一站汽车上乘客的人数是" + count);

        //第二站:上去3位乘客,下来1位乘客
        count = count + 3;
        count = count - 1;
        System.out.println("第二站汽车上乘客的人数是" + count);

        //第三站:上去4位乘客,下来2位乘客
        count = count + 4;
        count = count - 2;
        System.out.println("第三站汽车上乘客的人数是" + count);

        //第四站:下来一位乘客
        count = count - 1;
        System.out.println("第四站汽车上乘客的人数是" + count);

        //第五站:上去一位乘客
        count = count + 1;
        System.out.println("第五站汽车上乘客的人数是" + count);
        System.out.println("终点站到了,车上一共" + count + "位乘客");
    }
}

程序运行结果

image

10.2 使用变量存储电影信息并打印输出

电影信息包括电影名称、主演、年份,评分,要求使用变量存储并输出变量值

image

VariableExample2MovieInfo.java演示使用变量存储电影信息并打印输出

package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 变量和数据类型案例2:存储电影信息
 * 电影信息包括电影名称、主演、年份,评分,要求使用变量存储并输出变量值
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/13 10:17
 * @since Java17
 */
public class VariableExample2MovieInfo {
    public static void main(String[] args) {
        // 
        String name = "红海行动";
        String major = "张译/黄景瑜/海清/杜江";
        int year = 2018;
        double score = 9.3;
        System.out.println("电影信息如下");
        System.out.print("电影名称:" + name);
        System.out.print("主演:" + major);
        System.out.print("上映年份:" + year);
        System.out.print("评分:" + score);
    }
}

程序运行结果

image

10.3 使用变量存储商品信息并打印输出

商品信息包括型号、价格、品牌、颜色

image

VariableExample3ProductInfo.java实现使用变量存储商品信息,并打印输出

package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 变量和数据类型案例3:使用变量存储商品信息,并打印输出
 * 商品信息包括型号、价格、品牌、颜色
 *
 * @author tony 18601767221@163.com
 * @version 2023/7/13 10:19
 * @since Java17
 */
public class VariableExample3ProductInfo {
    public static void main(String[] args) {
        // https://item.jd.com/100053748386.html#crumb-wrap
        String model = "P60 Pro";
        double price = 7288.00;
        String brand = "HUAWEI";
        String color = "羽砂黑";

        System.out.println("手机信息如下:");
        System.out.print("手机型号:" + model);
        System.out.print("价格:" + price);
        System.out.print("品牌:" + brand);
        System.out.print("颜色:" + color);
    }
}

程序运行结果

image

10.4 使用变量存储淘宝用户登录信息并打印输出

淘宝用户登录信息包含用账号名和登录密码

image

VariableExample4TaobaoLogin.java实现使用变量存储淘宝用户登录信息并打印输出

  package net.ittimeline.java.core.foundational.syntax.variable;
    
    /**
     * 使用变量存储淘宝用户登录信息并打印输出
     *
     * @author tony 18601767221@163.com
     * @version 2023/7/13 10:29
     * @since Java17
     */
    public class VariableExample4TaobaoLogin {
        public static void main(String[] args) {
            String accountName = "tony";
            String password = "Java12312..";
            System.out.println("淘宝用户登录信息  账号名:" + accountName + " 密码:" + password);
    
        }
    }

程序运行结果

image

posted @ 2023-07-28 23:21  ittimeline  阅读(89)  评论(0编辑  收藏  举报  来源