一、JAVA语言基础
1.java概述
1.1简介(了解一下)
计算机语言的概念
计算机语言(Computer Language)是人与计算机之间通信的语言,它主要由一些指令组成,这些指令包括数字、符号和语法等内容,程序员可以通过这些指令指挥计算机进行工作。计算机语言的种类非常多,总的来说可以分成机器语言、汇编语言、高级语言(最简单)三大类。
机器语言都是由二进制的0和1组成的编码,不便于记忆和识别。 汇编语言采用了英文缩写的标识符,容易识别和记忆; 高级语言采用接近于人类的自然语言进行编程,进一步简化了程序编写的过程。 因此,目前编程语言大多是高级语言。
Java是一种高级计算机语言,它是由SUN公司(现已被Oracle公司收购)于1995年5月推出的一种可以编写跨平台应用软件、完全面向对象的程序设计语言。Java语言简单易用、安全可靠,自问世以来,与之相关的技术和应用发展得非常快。在计算机、移动电话、家用电器等领域中,Java技术无处不在。
针对不同的开发市场,SUN公司将Java划分为三个技术平台,它们分别是JavaSE、JavaEE和JavaME。
● Java SE(Java Platform Standard Edition)标准版
是为开发普通桌面和商务应用程序提供的解决方案。JavaSE是三个平台中最核心的部分,JavaEE和JavaME都是从JavaSE的基础上发展而来的,JavaSE平台中包括了Java最核心的类库,如集合、IO、数据库连接以及网络编程等。
● Java EE(Java Platform Enterprise Edition) 企业版
是为开发企业级应用程序提供的解决方案。Java EE可以被看作一个技术平台,该平台用于开发、装配以及部署企业级应用程序,主要包括Servlet、JSP、JavaBean、JDBC、EJB、Web Service等技术。
● Java ME(Java Platform Micro Edition) 小型版
是为开发电子消费产品和嵌入式设备提供的解决方案。JavaME主要用于小型数字电子设备上软件程序的开发。例如,为家用电器增加智能化控制和联网功能,为手机增加新的游戏和通讯录管理功能。此外,Java ME还提供了HTTP等高级Internet协议,使移动电话能以Client/Server方式直接访问Internet的全部信息,提供高效率的无线交
1.2.java语言的特点(还是了解)
- 简单性: Java语言是一种相对简单的编程语言,它通过提供最基本的方法完成指定的任务。程序设计者只需理解一些基本的概念,就可以用它编写出适用于各种情况的应用程序。Java丢弃了C++中很难理解的运算符重载、多重继承等概念;特别是Java语言使用引用代替指针,并提供了自动的垃圾回收机制,使程序员不必担忧内存管理。
- 面向对象: Java语言提供了类、接口和继承等原语,只支持类之间的单继承,但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为implements)。Java语言全面支持动态绑定,而C++语言只对虚函数使用动态绑定。总之,Java语言是一个纯粹的面向对象程序设计语言。
- 安全性: Java安全可靠,例如,Java的存储分配模型可以防御恶意代码攻击。此外,Java没有指针,因此外界不能通过伪造指针指向存储器。更重要的是,Java编译器在编译程序时,不显示存储安排决策,程序员不能通过查看声明猜测出类的实际存储安排。Java程序中的存储是在运行时由Java解释程序决定。
- 跨平台性: Java通过JVM(虚拟机)以及字节码实现跨平台。Java程序由javac编译器编译成为字节码文件(.class)文件, JVM中的Java解释器会将.class文件翻译成所在平台上的机器码文件,执行对应的机器码文件就可以了。Java程序只要“一次编写,就可到处运行”。
- 支持多线程: Java语言支持多线程。所谓多线程可以简单理解为程序中多个任务可以并发执行,多线程可以在很大程度上提高程序的执行效率。
- 分布性: Java是分布式语言,既支持各种层次的网络连接,又可以通过Socket类支持可靠的流(stream)网络连接。用户可以产生分布式的客户机和服务器,在这个过程中,网络变成软件应用的分布式运载工具。
1. 3.JAVA发展史
-
1991年 Java的前身"Oak"语言开始着手研发
-
1992年 "Oak"语言开发成功后,由于各种原因无法进入市场,被搁置了下来
-
1995年5月23日 ,在 Oak 更名为 Java 后,Java 在 Sun world 会议上正式诞生
-
1996年1月23日 Sun 发布 JDK 1.0 版本
-
1997年2月18日 Sun 发布 JDK 1.1 版本
-
1998年12月4日 Sun 发布 JDK 1.2.0 版本 在 JDK 1.2 版本中 sun 公司把 Java 体系分为 J2SE、J2ME、J2EE 三个方向
-
2000年5月8日 Sun 发布J2SE 1.3.0 版本,代号Kestrel(美洲红隼)
-
2002年2月13日 Sun 发布 J2SE 1.4.0 版本,代号Merlin(灰背隼)
-
2004年9月30日 Sun 发布 Java SE 5.0 版本,代号Tiger(老虎)
-
2006年12月12日 Sun 发布 Java SE 6 版本(这个版本开始没有后缀.0),代号Mustang(野马)
-
2006年11月13日,Sun 公司宣布将Java技术开源
-
2006年11月13日,Sun 公司宣布,它将在 GNU 通用公共许可第二版,类路径例外(即 GNU General Public License, version 2, with the Classpath Exception)下,将Java技术作为免费开源软件对外发布,并陆续开放源代码。
-
2006年11月 Sun 公司成立了 OpenJDK 开源社区组织,OpenJDK诞生
-
2006年11月 Sun 公司成立了 OpenJDK 开源社区组织(不只有OpenJDK中的jdk项目,还有和Java相关的其它开源项目),对源码进行独立管理
-
2009年,甲骨文(Oracle)公司宣布收购 Sun(Stanford University Network Microsystems)公司
-
2010年,Java编程语言的共同创始人之一詹姆斯·高斯林(大胡子,要记住)(Java之父)从Oracle公司辞职。
-
2011年7月11日,Oracle 发布 Java SE 7 LTS(LTS长久有效版) 版本,代号 Dolphin(海豚)
-
2014年3月18日,Oracle 发布 Java SE 8 LTS 版本
-
2018年微软收购了 GitHub,
-
2019年7月9日 IBM 也收购了 红帽公司(红帽现接管了 OpenJDK 8、OpenJDK 11 更新项目(之前接管了 OpenJDK 6、7 的更新项目))。 Java 顿时面临如 Python 2 与 Python 3 那般分裂的危机,
-
2017年9月21日,Oracle 最终发布了 Java SE 9 版本 2017年8月,Oracle决定将Java EE 移交给开源组织,最后Eclipse基金会接手,此时是Java EE 8版本,Java EE已经正式更名为 Jakarta EE
-
2018年3月20日,Oracle 发布 Java SE 10 版本 2018年3月27日,Android 的 Java 侵权案有了最终判决,法庭裁定 Google 赔偿 Oracle 合计 88 亿美元,要知道 2009 年 Oracle 收购 Sun 也就只花了 74 亿(如果不考虑通货膨胀的话)
-
2018年3月,Oracle正式宣布将Java EE 移交给开源组织 Eclipse基金会,此时是Java EE 8版本 从 JDK 10 起,HotSpot 中又加入了一个全新的即时编译器:Graal 编译器
-
2018年9月25日,Oracle 发布 Java SE 11 LTS 版本
自2017年9月 JDK 9 发布开始,Oracle OpenJDK 诞生,Oracle在免费的开源许可证(GPL v2 + CPE)(类似于Linux)下提供 OpenJDK 二进制构建版本。Oracle 提供的 OpenJDK 版本的可用性和社区支持在 jdk.java.net 上单独列出。
从 Java 11 开始,Oracle JDK 构建 和 Oracle OpenJDK 构建 将基本相同
-
2019年3月19日,Oracle 发布 Java SE 12 版本
-
2019年9月19日,Oracle 发布 Java SE 13 版本
-
2020年3月17日,Oracle 发布Java SE14 版本
-
2020年9月15日,Oracle 发布Java SE 15 版本
-
2021年3月16日,Oracle 发布Java SE 16 版本
-
2021年9月14日,Oracle发布Java SE 17 LTS 版本
-
2022年3月22日,Oracle发布Java SE 18 版本
-
2022年9月20日,Oracle发布Java SE 19 版本
-
2023年3月21日,Oracle发布Java SE 20版本
-
2023年9月19日,Oracle发布Java SE 21 LTS版本
2.开发环境搭建(重点)
2.1开发环境介绍
开发环境,顾名思义,就是我们在开发程序时所需要的环境。打个比方,人想要生活,就必须要有一定的环境,如氧气,水,食物等。再比如,人饿了想要吃饭菜,就必须先有吃饭菜的环境,如饭桌,椅子,筷子,勺子,盘子,碗等,这些都属于环境的一部分。
做java开发,也是需要特定环境的,我们称之为java开发环境。
JDK,全称Java Development Kit(Java开发工具包),就是java的开发环境。说的大白话一点,它就是一个资源包,我们只需要把这个资源包安装到你的电脑上,你就可以在这个环境下进行java
JDK 由两大部分组成,分别为 开发工具和运行环境。
1)开发工具
- javac – 编译器,将源程序转成字节码
- jar – 打包工具,将相关的类文件打包成一个文件
- javadoc – 文档生成器,从源码注释中提取文档
- jdb – debugger,查错工具
- java – 运行编译后的java程序(.class后缀的)
- Javap:Java反汇编器,显示编译类文件中的可访问功能和数据,同时显示字节代码含义。
2)运行环境(JR)
即Java Runtime Environment,简称JRE。即,程序员编写的java程序运行和测试所需要的环境,包含JVM和系统类库。
JVM:
是java virtual michine的简写,一个可以模拟计算机能力的程序。
Java程序在编译之后会生成.class字节码文件,这个文件会被加载到JVM虚拟机中运行。
是Java跨平台的最重要的部分。
系统类库:
即我们在开发程序时,系统提供给我们的资源(类)库(java.lang,java.math,java.util,java.sql,java.text等)
3)JDK,JRE,JVM三者的关系
2.2 JDK的安装(重要)
首先你需要下载一个jdk,下完之后要配置环境变量。
链接:https://pan.quark.cn/s/25c0d5a71f93
提取码:EA1u
需要JDK8的上面自提。
jdk的环境变量的配置
1.从jdk1.5版本(jdk5)开始后,只需要配置一个环境变量即可。如果只做java开发。即path这个环境变量,注意:该变量里有很多自带的系统目录,不能随便删除。在path变量里,只需要添加jdk里所有的指令所在的位置。 如: path 里新添加一个C:\Program Files\java\jdk1.8.0 221\bin了
打开环境变量的方法:右键点击此电脑-->选择属性-->然后选择高级系统设置-->打开后就能看到环境变量了。在环境变量里面找到系统变量里的path路径。
如下图所示:
1.右键点击此电脑,选择属性
2.在界面右边找到高级系统设置
3.选择环境变量
4.找到path路径,点击编辑。
5. 点击新建
6. 输入bin所在的路径,建议一直点上移移到最上面。
7.然后点击确定就可以了。以上是不用JAVA HOME 设置环境变量的方法。
8、如果配置了JAVA HOME: C:\Program File\java\jdk1.8.0 221
9.在path里面新建写法如下 %JAVA HOME%\bin
最好也是移到最上面。
2.JAVA HOME环境变量说明:
变量名: JAVA HOME
变量值: 就是bin目录,jre目录,lib目录所在的位置,
如果是默认地址的话就是这个地址:C:\Program File\java\jdk1.8.0 221
JAVA HOME这个环境变量,不一定是要给java开发工具使用的,有可能别的工具也需要该环境变量,比如tomcat的运行。从JDK5开始,只需要配置path即可,但是有些软件,比如tomcat,可能会需要JAVA_HOME这个变量。
3.如何检查是否配置成功:
java -version
javac
WIN+R打开命令提示符,不会的话在搜索栏搜命令提示符,点击也行。
如下图:
上述两个指令运行后,只要不出现“不是内部或外部指令”那基本上就是成功了。
2.3.JDK的目录介绍
为了更好地学习JDK,初学者需要对JDK安装目录下的子目录及文件的作用有所了解,接下来分别对JDK安装目录下的子目录进行介绍。
-
bin目录:该目录用于存放一些可执行程序,如javac.exe(Java编译器)、java.exe(Java运行工具)、jar.exe(打包工具)和javadoc.exe(文档生成工具)等。
-
include目录:由于JDK是通过C和C++实现的,因此在启动时需要引入一些C语言的头文件,该目录就是用于存放这些头文件的。
-
jre目录:此目录是Java运行时环境的根目录,它包含Java虚拟机,运行时的类包、Java应用启动器以及一个bin目录,但不包含开发环境中的开发工具。
-
legal目录:通常包含了一些法律相关的文档和许可证文件。它主要用于提供有关JDK 8的许可和使用条款的信息。
-
lib目录:lib是library的缩写,意为Java类库或库文件,是开发工具使用的归档包文件。
-
javafx-src.zip:该压缩文件内存放的是Java FX(Java图形用户界面工具)所有核心类库的源代码。
-
src.zip:src.zip为src文件夹的压缩文件,src中放置的是JDK核心类的源代码,通过该文件可以查看Java基础类的源代码。
-
LICENSE和release:版权、许可文件。
-
README等说明性文档。
bin目录中
-
javac:编译器,将源程序转成字节码
-
java:打包工具,将相关的类文件打包成一个文件
-
javadoc:文档生成器,从源码注释中提取文档
-
jar:这个工具用于创建、查看和提取Java存档文件(.jar文件)。Java存档文件是一种用于打包Java类、资源文件和其他相关内容的文件格式。
-
jdb:debugger,查错工具
-
javah:产生可以调用Java过程的C过程,或建立能被Java程序调用的C过程的头文件。
-
javap:Java反汇编器,显示编译类文件中的可访问功能和数据,同时显示字节代码含义。
-
keytool:用于管理密钥和证书
-
jps:用于列出正在运行的Java进程
-
jstat:用于监视Java应用程序的统计信息
2.4环境变量
上面已经讲过怎么样配置环境变量了。
那么为什么要配置环境变量
在JDK安装完成后, bin目录中存放了若干个对Java程序进行操作的命令,包括javac和java。但是 如果以后每次需要使用到这些命令的时候,都要从磁盘根目录开始找这些命令,会非常的麻烦。因 此,我们需要将bin目录添加到环境变量中,实现在任意的路径下,都可以直接使用相关的命令来 进行对Java程序的处理。另外,某些IDE是需要读取环境变量中的JDK的路径,来识别Java环境。如果没有配置环境变量,会 导致这些IDE无法正常工作。
3. 标识符
3.1概念
Java语言中,对于变量,常量,函数,语句块来说,都是有名字的,这些名字,我们统统称之为Java标识符。
作用:标识符是用来给类、对象、方法、变量、接口和自定义数据类型命名的。
3.2 标识符的命名规则
可以由字母,数字,_和$,这四种的任意多个组成,但是数字不能开头
大小写字母敏感,需要特别注意(严格区分大小写)
可以使用汉字,但是不建议使用
不能使用关键字,如int,for,if等
尽量做到见名知意,多个单词时需要符合驼峰命名法
驼峰命名法: 在遵循见名知意的前提下,有些时候一个标识符的命名可能比较长,由多个单词组成。
大驼峰: 组成一个标识符的每一个单词的首字母都是大写的。
小驼峰: 首单词除外,从第二个单词开始,每一个单词的首字母都是大写的
3.3命名约定
以下只是命名约定,不按照约定命名规则命名代码也不一定是错误的,但在Java代码的规则中普遍遵循“约定大于配置”,因此在实际代码开发中应尽量遵循约定的命名规则;
1)类和接口名:每个单词的首字母都要大写,其他字符小写。
2)方法名:首字符小写,其余单词的首字母大写,尽量少用下划线。(小驼峰)
3)常量名:全部大写字母,单词与单词之间用下划线分隔。
4)变量名:首字符小写,其余单词的首字母大写。不用下划线,少用美元符号。给变量命名是尽量做到见名知义。(小驼峰)
常量和变量的定义
变量: 如果某一个标识符表示的数据,在程序运行的过程中是可以发生改变的。
常量: 如果某一个标识符表示的数据,在程序运行的过程中是不能发生改变的。
4.java的入门案例
每一种语言的开始,都是始于"Hello World"。那么来欢迎你的第一个程序降世吧。
先来写第一个代码:
public class MyFirstProgramer{
public static void main(String[] args){
System.out.println("Hello World");
}
}
格式:
修饰词 关键字 标识符(类名)使用大驼峰命名法
public class ClassName{
}
规则如下:
- 程序员编写的文件的扩展名.java 叫java源文件。
- 源文件中的public 修饰的class只能有一个。说明文件中可以有多个class类
- public修饰的类的名字要尽量与文件名一模一样。
- 类名后面的花括号及其里面的内容,称之为类体。
- 类体的开始符号"{"应该位于类名后 结束符号'}'应该位于开始符号所在行的首字符的下面
- 被包含的内容,应该缩进两个或者是四个空格。也就是一个Tab键。
代码部分解释:
main方法: 固定写法,public static void main(String[] args){
}
作用:程序的入口,即JVM会先执行main方法。
输出语句:System.out 会得到一个输出流,默认指向了控制台
.println() : 调用流的打印并换行功能,将小括号里的数据打印到控制台,然后插入换行符。
结果截图:
现在,你的第一个代码已经诞生了!
5.变量
5.1 概念
jvm在其管理的内存中会开辟很多个空间、这些空间用来存储数据,而这些存储空间里的数据也会根据我们不同时间的不同需求而变化,那么,这样的存储空间,我们需要给他们命名,我们可以通过这些名字来操纵(使用)这些存储空间。 这些名字就是我们所说的变量。(存储空间的名字就是变量。)
5.2变量的应用:
1.语法规则
变量必须先声明和初始化
--声明:就是规定该变量要存储的数据类型,也称为定义变量
int myNumber; 注意:一句话说完,使用分号表示结束。英文输入法
--初始化:就是第一次给变量赋值。
--初始化的时机,分别是声明时直接初始化,和使用时在初始化。
-变量可以重复的存和取。
--存: 使用等号给变量赋值
--取: 使用变量给其他赋值
public class VariableDemo{
public static void main(String[] args){
//练习1:声明一个int类型的变量,变量名是数字number。
int number;
number=100; //第一次赋值,叫初始化。
//练习2:使用输出语句,进行打印。
System.out.println(number);//注意:想要输出变量里的值,直接写在括号里面,千万不要添加双引号。
//练习3:定义一个long类型的变量time,直接赋值为1000,然后输出打印。
long time = 1000;
System.out.println(time);
//练习4:定义int类型变量num,打印该变量。
int num;
//System.out.println(num);//会报编译错误
//除了变量在声明的位置,出现在其他任何位置上,都是在使用该变量,那么变量在使用前必须初始化。
int a = 10;//内存中开辟了一个存储空间a,存了一个int类型的10
int b = 20;
int c = a + b;//将a和b的值取出来然后计算,结果30再存入变量c里面。
a = 5;//将5存入a变量里,原有的10被5覆 盖掉了。
a = 50;//将50存入a变量里,原有的5被50覆盖。
a = a + 6;//使用a里的50 与 6 做加法运算,结果56再次存入变量a中,把之前的50覆盖掉了。
System.out.println(a);
}
}
结果截图:
变量的应用(续)
-变量的操作必须与声明时所强调的类型一致。 简短点,也就是类型必须一致,否则类型不匹配。
-变量是有自己的作用域的。 大白话:变量有自己的使用范围。
1)作用域:从声明处开始,一直到它所在的花括号的结束符号位置。
2)在该作用域内,变量不能重复声明(定义),出了该作用域,需要重新定义(声明)
代码如下
public class VariableDemo02{
public static void main(String[] args){
int number =10; //定义一个int类型的变量number,初始化为10
//number = 3.14; // 3.14是小数类型,不是int类型,所以会报编译错误
//研究变量作用域
int a = 100;
if(a>50){
int b = a *2;
}else{
int c = a -10;
//long a = 100;//a这个变量已经在该作用域存在,因此不能重复定义
}
long c = 10000;//该处的c变量是重新定义的,该作用域没有重复
System.out.println(a);
//System.out.println(b);//b这个变量已经出了它自己的作用域。
System.out.println(c);//该处的c使用的是long类型的c。
}
public void run(){
System.out.println(number);//变量number想要使用,需要在使用前声明和初始化。
}
}
结果展示:
上述代码b的作用域只到它的下一行的" } "处。
5.3变量的分类
按照位置分类
-成员变量:在方法外,类体里定义的变量
-局部变量:在方法里定义的变量注意:类外面不能有变量的声明
按照类型分类
-基本数据类型(原始数据类型(只有八种))
-引用数据类型(包括数组)
代码:
public class VariableDemo03{
int age = 10;//成员变量
public static void main(String[] args){
//下面三个变量都是局部变量
int number = 1;
int num = 100;
String myName ="lucy";
}
String name ="michael";//成员变量
String gender = "女";//成员变量
public void run(){
int a = 100;//局部变量
}
}
6. 数据类型
java中的数据类型可以分为两大类,一类是基本数据类型,另一类是引用类型。基本数据类型只有八种,因此,只需要记住这八种,这八种以外的,就全是引用数据类型了。
八种基本类型:
byte , short , int , long(整数类型) double , float(浮点型) char(字符型) boolean(布尔类型)。
6.1 整数类型
类型名称 | 占用存储空间 | 数值范围 | 使用场景 |
---|---|---|---|
byte | 1字节(8位) | -2^7^~2^7^-1(-128 ~ 127) | 存储字节数据(较常用) |
short | 2字节(16位) | -2^15^ ~ 2^15^ -1(-32768-32767) | 兼容性考虑(很少使用) |
int | 4字节(32位) | -2^31^ ~ 2^31^-1(-2147483648~2147483647) | 存储普通整数(常用) |
long | 8字节(64位) | -2^63^ ~ 2^63^-1(正负922亿亿,19位数10进制) | 存储长整数(常用) |
Java各整数类型都有固定的表数范围和字段长度,这样不受具体OS的影响,保证了java的可移植性。
- 赋值时,不能超出各自的范围,否则编译不通过。
- 整数字面量,也叫整数直接量(literal),就是直接写出来的整数,是int类型。
- int字面量(注意不是int定义的类型),只要没有超出byte或者short的范围,是可以直接赋值给byte或short类型的变量的 (自动截断高位的0或1)
- int字面量,可以直接给long类型的变量赋值。 (自动补全高位的32个0或1)
- long字面量,需要在整数后面添加小写或者大写的L。
测试代码:
public class TypeDemo01{
public static void main(String[] args){
byte b1 = 10;
//byte b2 = 128;//编译错误。byte的最大值是 127.
int n1 =2147483647;//int的最大值
//int n1 = 2147483648;//超出int范围,编译错误。
short s1 = 10;//10是int类型,因为没有超出short的范围,因此可以直接赋值给short
long lo1 = 1000; // 1000是字面值,是int类型。是可以直接赋值给long类型。
long lo2 = 10L; //10L是long类型,直接就是64位的二进制数
System.out.println(b1);
System.out.println(n1);
System.out.println(s1);
System.out.println(lo1);
System.out.println(lo2);
//long lo3 = 2200001111; //因为2200001111字面量就是int类型,不可以超出范围。
long lo4 = 2200001111l;// 使用long类型的字面量。
}
}
6.2.浮点数类型
基本数据类型之浮点数的学习
类型名称 | 占用内存大小 | 数值范围 | 使用场景 |
---|---|---|---|
float | 4字节(32位) | -3.403*E^38^ ~ 3.403*E^38^ | 存储单精度(较常用) |
double | 8字节(64位) | -1.79*E^308^ ~ 1.79*E^308^ | 存储双精度(常用) |
float: 单精度类型,能精确表示到小数点后6~7位,
能表示的整数部分的范围在38位 long的整数范围最大是19位(10进制位数)。
double:双精度类型,能精确表示到小数点后15~16位,
能表示的整数部分的范围在308位
-浮点数的字面量默认为double类型,如果想要float字面量,需要添加F/f
-浮点数的字面量也可以添加D/d,也可以省略。
-浮点数的写法: 比如5.12 3.12F 0.34/.34
代码:
public class TypeDemo02{
public static void main(String[] args){
//float f1 = 3.14;//编译错误,因为字面量是double
float f2 = 3.14f;//想要给float赋值,需要添加f/F
double d1=0.12;
double d2 = 10.1D;
double d3 = .12;
System.out.println(f2);
System.out.println(d1);
System.out.println(d2);
System.out.println(d3);
float f10 = 0.123456789f;//将小数存入float类型的变量空间f10里面
double d10 = 0.1234567890123456789;//将小数存入double类型的变量空间d10里面
System.out.println(f10);//取出来时,发现不是原来的值
System.out.println(d10);//取出来时,发现不是原来的值
double d101 = 3.0;
double d102 = 2.9;
System.out.println(d101-d102);//结果0.10000000000000009
//计算时有误差,并不是精确值
}
}
结果:
6.3 字符类型(char)
类型名称 | 占用内存大小 | 书面上所有字符 |
---|---|---|
char | 2字节(16位) | 如:‘中’,’a’,‘A’,‘0’,‘^’ |
1) 转义字符‘\’
对于不方便输出的字符,采用转义字符来表示,例如:
转义字符 | 含义 |
---|---|
\n | 表示回车符号 |
\r | 表示换行符号 |
\\ | 表示反斜杠 |
\‘ | 表示单引号 |
2) 字符集
事实上,char也是一个16位无符号整数,整数范围为0~65535。每个整数都是对应字符的编码。(理解字符集的概念)
java字符类型采用了Unicode字符集编码。Unicode是世界通用的定长字符集,所有的字符都是16位。
赋值特点:
1.任意字符,使用单引号引起来,引号里只能有且只有一个字符。
2.字符集: 字符与底层二进制一一对应的表
java语言里的字符使用的是Unicode字符集:每个字符都对应着一个16位的二进制数。(每个字符占用两个字节的空间大小。)
这些数的范围使用十进制表示就是0~65535;
即,除了赋值字符本身外,还可以赋值字符对应的数字,也就是0~65535中的任意一位。
注意:因为char可以表示0~65535这个范围内的整数(无符号整数),字母,数字,其他等特殊符号。
因此也可以参与计算。
代码:
public class TypeDemo03{
public static void main(String[] args){
char c1 = '中';
char c2 = '9';
char c3 = '_';
char c4 = '\t';//给变量赋值制表符 \t
char c5 = 't'; //给变量赋值普通的字母字符t
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4+"a");
System.out.println(c5);
//char c6 = '中国';//编译错误,单引号里只能放入一个字符。
//System.out.println(c6);
char c11 = 48;//字符0在unicode编码集里对应的那个整数
char c12 = 57;//字符9
char c13 = 90;//字符z
char c16 = 65;//字符a
char c14 = 97;//字符A
char c15 = 122;//字符Z
System.out.println(c11);
System.out.println(c12);
System.out.println(c16);
System.out.println(c13);
System.out.println(c14);
System.out.println(c15);
// 取出c21里的数据与7做加法运算,运算时使用字符对应的数字97参与运算,
// 结果104,存入char类型的变量里,如果打印,应该是104队友的字符H。
char c21 = 'a';
char c22 =(char) (c21+7);
System.out.println(c22);
}
}
结果:
6.4布尔类型(boolean)
类型名称 | 占用内存大小 | 值 |
---|---|---|
boolean | 1字节(8位) | true/false |
类型名:boolean
值 true或false
作用:通常用于逻辑运算,true表示正确,false表示错误
逻辑运算:一般用于流程控制语句中,表示条件是否成立。
代码:
public class TypeDemo04{
public static void main(String[] args){
boolean f1 = true;
boolean f2 = false;
System.out.println(f1);
System.out.println(f2);
boolean f3 = 1<2;
System.out.println(f3);
}
}
结果:
6.5字符串类型
字符串类型:String,引用数据类型之一,是最常用的引用类型。
赋值特点: 双引号引起来,里面有0个以上的任意字符。
字符串可以进行拼接操作:使用+号。
注意 +号前后只要有一个是字符串类型,那就一定是做字符串拼接操作,拼接的结果也是字符串。
代码
public class TypeDemo05{
public static void main(String[] args){
String myName = "lucy";//4字符
String str = "";//空字符串,字符的长度是0;
String space = " ";//空格 字符串,只有一个空格;
String str1 = " 你是最棒的 ";//str1的长度是7;
String str2 = "你 好";//str2的长度是3;
System.out.println(myName);
System.out.println(str);
System.out.println(space);
System.out.println(str1);
System.out.println(str2);
System.out.println("----字符串的拼接----");
String s1 = "中";
String s2 = "国";
String s3 = s1 + s2;//拼接的结果是"中国"
System.out.println(s3);
String s4 = s3 + "是最棒的";//"中国是最棒的"
System.out.println("s4的值:"+s4);
String r1 = 1+1+"2"+3+4;
System.out.println("r1的结果:"+r1);//r1的结果:2234
String r2 = 1+2+"3"+(4+5)+5*6;
System.out.println("r2的结果: "+r2);//33930
}
}
截图展示:
7.类型转换
什么是数据类型转换?
一个变量声明完成后,已经在内存上开辟好了空间,此时这个空间大小是不允许改变的。也就是说一个 变量的类型是不允许改变的。数据类型转换,其实就是定义一个新的指定类型的变量,然后将原来的变量的值给这个新的变量进行赋值。赋值完成后,新的变量和原来的变量值基本相同,并且类型也发生了改变,因此,这个过程就被称为数类型转换。
在数据类型转换中,分为两种转型:自动类型转换 和 强制类型转换
类型转换:基本数据类型之间可以进行转换。细分为:
1.自动类型转换(隐式类型转换)取值范围小的数据类型向取值范围大的数据类型转换,
是自动发生的,不需要我们进行任何操作。
取值范围从小到大排序:
byte-->short=char-->int-->long-->float-->double注意,byte,short,char之间不会相互转换,他们三者在计算时会转换为int类型进行计算。
2.强制类型转换:
取值范围大的数据类型向取值范围小的数据类型转换
注意:转换过程中,有可能发生精度损失或者是溢出
语法:小范围类型名 变量=(小范围类型名)大范围变量
代码:
public class TypeTransform01{
public static void main(String[] args){
byte b1 = 10;
//b1变量里存的是8位二进制的10。存入s1时,自动变为了16位二进制的10
short s11 = b1;
//s1变量里存的是16位二进制的10。存入n1时,自动变为了32位二进制的10
int n1 = s11;
//b1变量里存的是32位二进制的10。存入s1时,自动变为了64位二进制的10
long n2 = n1;
double d1 = n2;//long类型的10转成double类型的10.0;
System.out.println("--------强制类型转换-------");
double d10 = 3.14;
long n10 = (long)d10;//强制转换,精度损失了。3.14转成3小数点后的数据丢失了
System.out.println(n10);
int n11 = (int) n10;//强制转换,64位的数字3转成了32位数字3。
int n12 = 32767; //00000000 00000000 01111111 11111111
short s1 = (short)n12;//编译期间,编译器的工作开始只做语法价差,不考虑变量的值。
System.out.println("short类型的s1的值" + s1);
int n13= 32768; //00000000 00000000 10000000 00000000
short s12 = (short)n13;//强制转换,发生了溢出(值改变了)
System.out.println("short类型的s12的值" + s12);
byte b11 = (byte) s12;//强制转换,
System.out.println("b11的值:"+b11);
//注意 int类型的字面量,如果没有超出byte,short,char的范围时,
//是可以直接给这些类型的变量进行赋值。因为底层会自动将前面的0或1截断。
byte b100 = 10;
short s100 = 30000;
char c100 = 60000;
short b101 = (byte) 128;//抄范围了,就需要强制转换。
}
}
结果:
8.常用的运算符
在java运算过程中,无论是什么运算,都应该遵循以下三种形式:
-
当有多种类型的数据混合运算时,系统首先自动将所有数据转换成取值范围最大的那种数据类型,然后再进行计算。
-
byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型,然后在运算。如果有其他取值范围大的类型,会选择范围最大的那种类型转换。
-
有可能会发生溢出现象(封闭式运算)。
最大值+1 就变成了最小值。最小值-1 就变成了最大值。
两个整数运算时,可以能会出现溢出情况,即超出整数范围的运算。正数溢出,会变成负数;负数溢出,会变成整数。我们也称之为封闭式运算。
犹如蛇头咬住了蛇尾。 转圈了。
8.1 算术运算符
算术运算符有 + - * / %,其中加减乘跟我们之前数学中学过的几乎一样的规则。着重介绍一下子"/"和"%"。
%(取余):取模运算符,即求余数, 5 % 3 = 2
/ (取整):整型与整型的计算结果,还是整型。最终除如果得到一个浮点型的结果,那么这个浮点型的数字 会自动的转成整型数字,浮点型转整型,舍去小数点后面所有的内容,直接保留整数部分。除法运算时,只要有一个是浮点类型,那就是真正的除法运算。
测试代码如下:
public class SymbolDemo01{
public static void main(String[] args){
byte b1 = 10;
byte b2 = 20;
int b3 = b1+b2;//b1转成int,b2转成int,然后两个int做运算。
byte b4 = (byte)(b1+b2);//计算结果是int类型,然后将结果进行强转。
int n1 = 100;
long n2 =10;
long n3 = n1-n2;//n1先转成long类型,然后和n2做运算。结果是long类型。
byte num1 = 2;
byte num2 = 127;
byte num3 =(byte)( num1*num2);//溢出了
System.out.println("num3: "+num3);//-2
//两个整数在做除法运算时,实际上是结果值取整数部分,曲调小数部分。
long num4 = 10;
int num5 = 4;
long num6 = num4/num5;
//除法运算时,只要有一个是浮点类型,那就是真正的除法运算
double num7 = 10.0;
int num8 = 4;
double num9 = num7 /num8;
//取模运算(求模,求余数)
long num10 = 20;
int num11 = 6;
long num12 = num10%num11;
System.out.println(num12);
}
}
结果截图:
总结,注意类型间的转换关系,容易发生编译错误,注意溢出现象和除号和百分号的不一样的地方。
算术运算符还包括自增(++)、自减(--)。
算数运算符之自增自减运算符
++:
符号在变量前:先加后赋值
变量先自增,然后将变量的新值赋值给表达式
符合在变量后:先赋值再加
现将变量的值赋值给表达式,然后变量再增1
--:
符号在变量前:先减后赋值
变量先自减,然后将变量的新值赋值给表达式
符合在变量后:先赋值再减
现将变量的值赋值给表达式,然后变量再减1
揉成一句话:
符号在前:先运算再赋值
变量先加一或减一,再将新值赋给表达式
符号在后:先赋值再运算
测试代码如下:
public class SymbolDemo02{
public static void main(String[] args){
int i =10;
i++;
System.out.println(i);//11
int m=100;
++m;
System.out.println(m);//101
int n=2;
n--;
System.out.println(n);//1
--n;
System.out.println(n);//0
/*上述代码中,不管是自增还是自减,输出语句里输出的都是里面的变量,因此就是在自增或自减
当自增或自减这个式子参与到其他运算符号当中,就需要考虑类上面写的注释了*/
int x=1;
int m1 =x++;
System.out.println("x的值"+x);
System.out.println("m的值"+m1);
m = ++x;
System.out.println("x的值:"+x);//6
System.out.println("m的值:"+m);//6
x=5;
m = ++x + x++ + ++x - --x;
System.out.println("x的值:"+x);//7
System.out.println("m的值:"+m);//13
int y = 5;
int z = 6;
// 5+6+8+5+8
z = y++ + z++ + ++z + --y + z--;
System.out.println("y的值:"+y);//5
System.out.println("z的值:"+z);
}
}
结果截图:
注意:计算时,不要忘记前面自增没有赋值的自增运算。
8.2 赋值运算符
=是一个赋值运算符,将等号右边的值给左边的变量进行赋值。
运算符之赋值运算符 =:最简单的赋值运算符,将等号后面的表达式或者变量的值赋值给等号前面的变量 +=: 如:a+=b 相对于 a= a + b -=: 如:a-=b 相对于 a= a - b *=: 如:a*=b 相对于 a= a * b /=: 如:a/=b 相对于 a= a / b %=: 如:a%=b 相对于 a= a % b
测试代码:
public class AssignSymbol01 {
public static void main(String[] args) {
int a = 10;
int b = 20;
a += b; //相对于a = a + b
System.out.println(a);//30
System.out.println(b);//20
a -= b;//相对于a = a - b
System.out.println(a);//-10
int c = 3;
int d = 6;
c *= d;
System.out.println(c);// 18
c = 15;
c /= d;
System.out.println(c);
int x = 15;
int y = 6;
x %= y;
System.out.println(x);
System.out.println("Hello World");
}
}
结果:
8.3 关系运算符
运算符之关系运算符
>, >=, < , <= , == , !=
作用:用于判断两边的大小关系
返回值boolean类型
代码:
public class SymbolDemo01 {
public static void main(String[] args) {
int x = 10;
int y = 20;
System.out.println(x>y);//f
System.out.println(x>=y);//f
System.out.println(x<y);//t
System.out.println(x<=y);//t
System.out.println(x==y);//f
System.out.println(x!=y);//t
}
}
结果看注释就好啦。比较简单。
8.4 逻辑运算符
运算符孩之逻辑运算符: &:与,两真即为真,有任意一个为假,结果就是假。 |:或,两假即为假,有任意一个为真,结果就是真。 !:非,非真即假,非假即真。 ^:异或,两个相同为假,两个不同为真。 在java中,一般研究的是短路逻辑运算符 第一个条件如果已经可以确定最终结果,那么第二个条件就不在执行,节省时间。 &&: 短路与: 一假则假,全真为真。 true&&true ==>true true&&false ==>false false&&true ==>false false&&false ==>false 针对于短路与来说:第一个是false时,不再执行第二个条件,管它是true还是false. ||: 短路或: 一真则真,全假为假。 true&&true ==>true true&&false ==>false false&&true ==>false false&&false ==>false 针对于短路或来说:第一个是true时,不再执行第二个条件,管它是true还是false
测试代码:
public class LogicSymbolDemo01 {
public static void main(String[] args) {
//验证短语&&
int a = 1,b = 2,c = 3,d = 4;
boolean f = a < b && c < d ;
System.out.println("f的值:"+f);
f=a<b && c > d ;
System.out.println("f的值:"+f);
f=a>b && c++ < d ;
System.out.println("f的值:"+f);
System.out.println("c的值:"+c);//如果c是3,表示第二个条件没有执行。
f=a>d && c > d++ ;
System.out.println("f的值:"+f);
System.out.println("d的值:"+d);//如果d是4,表示第二个条件没有执行。
int m=1,n=2,x=3,y=4;
boolean p=m<n || x<y;
System.out.println(p);//t
p=m<n || x>y;
System.out.println(p);//t
p=m>n || x<y;
System.out.println(p);//t
p=m>n || x>y;
System.out.println(p);//f
p= m<n || x++<y;
System.out.println(p);
System.out.println(x);//如果x是3表示没有执行,第一个条件是true,可以确定最终答案。,因此没有执行自增运算。
// p=m<n || x++>y;
//! 非真既假,非假即真。
f=!(1>2);
System.out.println(f);
f=!f;
System.out.println(f);
}
}
结果为:
注意:需要注意的是短路问题,短路与当第一个为假时发生短路。短路非当地一个为真时发生短路。发生短路就是不执行后面的代码了,因为没有必要了。
8.5 三元运算(三目运算 条件运算)
三元运算由于之前老师教的,加上我自己的习惯,我更喜欢称它为问好表达式。
格式:
boolean类型表达式或者变量 ? 值1:值2;
当boolean为true时,返回值1,当为false时,返回值2.
注意:
该运算依然遵守混合运算时转成取值范围最大的那种类型。
值1和值2,可以时变量,也可以是具有返回值的表达式。
值1和值2的最终类型,需要能自动类型转换。
通常三目运算的最终结果,需要使用一个变量来接受,该变量的类型应该是值1或值2中的一个。
测试代码:
public class ThreeEyeSymbolDemo01 {
public static void main(String[] args) {
int a = 1;
int b = 2;
String str = a > b ? "是a大于b" : "a不大于b";
System.out.println(str);
int m = 10;
long n = 15;
long result = n%m==1?n:m; // 注意,需要考虑m和n在三目运算里都已经是long类型了。
System.out.println("result:"+result);
}
}
结果:
8.6算符优先级
运算符的简单分类:
运算符根据操作数的不同,可以分为:一元运算符、二元运算符、三元运算符。
一元运算符:只能操作一个操作数, ++ -- ! ~ + - (此时的+和-代表的是正负)
二元运算符:只能操作两个操作数,
三元运算符:只能操作三个操作数,三目运算符。
运算符的优先级
- 一元运算符 > 二元运算符 > 三元运算符
- 算术运算:乘除模 > 加减
- 逻辑运算:与 > 或
- 赋值运算符的优先级是最低的
- 小括号的优先级是最高的
第一章就先这样了,考试前忘记看第八章的前两节了,还以为没讲,考试有印象不会写了qaq。下一篇见~
补充:
9.scanner、random和math类
9.1scanner类
Scanner类的使用步骤:
步骤1: 导包 import java.util.Scanner;位置为package下面,类的上面
步骤2: 创建扫描器对象,并使用扫描器的变量引用该对象。
Scanner scan = new Scanner(System.in)
步骤3: 使用变量调用类里提供好的方法。 通常在调用前都会使用输出打印语句来进行友好提示.
System.out.println("请在控制台上输入一个年龄:");
int age = scan.nextInt();步骤4: 最后,如果后续代码不再使用扫描功能,需要关闭扫描器
scan.close();
常用方式:
基本数据类型相关方法:(没有char类型的)
- nextInt(); : 扫描控制台输入的int类型的数字
- nextByte(); : 扫描控制台输入的byte类型的数字
- nextShort(); : 扫描控制台输入的short类型的数字
- nextLong(); : 扫描控制台输入long类型的数字
- nextFloat(); : 扫描控制台输入的float类型的数字
- nextDouble(); : 扫描控制台输入的double类型的数字
- nextBoolean(); : 扫描控制台输入的boolean类型的数字
next(); : 扫描控制台上输入的字符串, 默认以空格或回车表示扫描结束。
nextLine(); : 扫描控制台上输入的字符串, 默认以回车表示扫描结束 。(可以打空格输入一句话。比如: i love you china. 但是尽量不要和其他扫描功能在一起使用,可能出现bug,不能输入,直接结束。)
注意:所有的nextXXX方法,都有阻塞效果,即阻止程序向下执行,除非扫描到数据并结束扫描,阻塞效果才会消失。
9.2random类
Random: 该类型一般用于产生随机数。比如随机一个范围的整数,或者小数。
使用步骤:
1. 导包操作, import java.util.Random;
2. 创建对象, Random r = new Random();
3. 调用相关功能
r.nextInt(number) :产生一个[0,number)范围内的任意整数。
r.nextDouble(): 产生一个[0,1)范围内的任意小数。
测试代码:
public class RandomDemo01 {
public static void main(String[] args) {
Random r = new Random();
//产生一个[0,10)区间内的一个整数。 生成等号前面的变量快捷键: alt+enter
int i = r.nextInt(10);
System.out.println("i=" + i);
//产生一个[0,10]区间内的一个整数
int i1 = r.nextInt(11);
System.out.println("i1=" + i1);
//产生一个[-5,5]区间内的一个整数
int i2 = r.nextInt(11)-5;
System.out.println("i2=" + i2);
//产生一个[0,1)区间内的任意一个小数
double v = r.nextDouble();
System.out.println("v=" + v);
}
}
结果:
进阶部分r.nextDouble()转化成整数范围:
总结公式:
闭区间[n,m]的公式 r.nextDouble()*(m+1-n)+n
开区间[n,m)的公式 r.nextDouble()*(m-n)+n
测试代码:
public class RandomDemo02 {
public static void main(String[] args) {
Random rd = new Random();
//随机[0,10)以内的任意小数 [0,1)*10
double v = rd.nextDouble() * 10;
//随机[0,10)以内的任意整数
int v1 = (int) (rd.nextDouble() * 10);
//随机[-6,6]的任意整数
int v2 = (int) (rd.nextDouble() * 13-6);
System.out.println(v2);
//随机[5,15]以内的任意整数
int v3 = (int) (rd.nextDouble() * 11+5);
System.out.println(v3);
/**
* 上述公式总结:
* [n,m] r.nextDouble() * (m-n+1)+n。(注意,n是什么就是什么,带着符号。
* [n,m) r.nextDouble() * (m-n)+n。
*
*/
}
}
结果:
9.3Math类
Math: 数学工具类,里面提供了很多关于数学方面的功能方式。
使用方式: 直接使用类名.具体方法名。
里面的内容分类:
静态常量: E 自然对数 PI 圆周率
常用函数:
max(): 取最大的数
min(): 取最小的数
random(): 随机数,范围[0,1) 与Random的nextDouble()效果一样
abs(): 取绝对值
取整函数:
ceil(): 向上取整(大于等于某一个数的最小整数) 比如 ceil(3.4) 得到 4
floor(): 向下取整(小于等于该数的最大整数) 比如floor(3.4) 得到3
rint(): 最近的整数 比如 rint(3.7) 得到4
比如 3.5 距离两边一样近,则返回偶数的整数
round(): 四舍五入指数函数:
pow(): 幂函数
sqrt(): 平方根
cbrt(): 立方根
三角函数(不常用):
sin()
cos()
asin()
acose()
tan()
atan()
测试代码:
public class MathDemo {
public static void main(String[] args) {
System.out.println("自然对数:"+Math.E);//double类型
System.out.println("圆周率: "+ Math.PI);//double类型
System.out.println("3和5比较,最大的是:"+Math.max(3,5));
System.out.println("3和5比较,小的是:"+Math.min(3,5));
System.out.println("-3的绝对值: "+Math.abs(-3));
//使用Math,random()产生一个随机数,默认[0,1)区间内的小数
//[5,10]
int n =(int) (Math.random()*6+5);
System.out.println("产生的随机整数"+n);
System.out.println("3.4向上取整"+ Math.ceil(3.4));
System.out.println("3.4向下取整"+ Math.floor(3.4));
System.out.println("3.5最近整数"+ Math.rint(3.5));//离两边一样近,返回偶数
System.out.println("3.5四舍五入后:"+ Math.round(3.5));
System.out.println("3的4次方"+ Math.pow(3,4));//81
System.out.println("8的开平方"+ Math.sqrt(8));
System.out.println("8的立方根"+ Math.cbrt(8));
}
}
结果:
这次应该是真的完事。下篇见。