目录
前言
学习javaSE的笔记,包括基础,语法,对象,集合,异常,IO流,多线程,反射
最好配合读程序练习题来学习感悟
一、概述
1.java语言发展史
詹姆斯·高斯林(James Gosling)在Sun公司参与"绿色计划",因为觉得使用C++有很多弊端,开发了一套语言--Oak(橡树)后改名为Java
2.Java语言版本
JDK 1.1.4 Sparkler 宝石 1997-09-12
J2SE 1.2 Playground 运动场 1998-12-04
J2SE 1.3 Kestrel 美洲红隼 2000-05-08
J2SE 1.3.1 Ladybird 瓢虫 2001-05-17
J2SE 1.4.0 Merlin 灰背隼 2002-02-13
JAVASE 5.0 (1.5.0) Tiger 老虎 飞跃的发展
JAVASE 6.0 (1.6.0) Mustang 野马
JAVASE 7.0 (1.7.0) Dolphin 海豚
3.Java语言平台
J2SE(Java 2 Platform Standard Edition)标准版:开发桌面应用程序,该技术体系是其他两者的基础
J2ME(Java 2 Platform Micro Edition)小型版:开发电子消费产品和嵌入式设备
J2EE(Java 2 Platform Enterprise Edition)企业版:开发企业应用程序,主要是web应用,该技术体系中包含大名鼎鼎的servlet、jsp等
4.Java语言特点
开源、跨平台
5.Java语言跨平台原理-可移植性
什么是跨平台:write once ,run anywhere!(一处编译,到处运行),通过java语言编写的应用程序在不同的系统平台上都可以运行
原理:在需要运行java应用程序的操作系统上,安装一个Java虚拟机(JVM Java Virtual Machine),由JVM来负责Java程序在该系统中的运行--不同平台对应不用的虚拟机即可
6.JRE和JDK的概述
JRE:java运行环境 java Runtime environment,JVM+类库,包括Java虚拟机和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
JDK:java开发工具 java development kit,JRE+JAVA的开发工具,包括编译工具(javac.exe) 打包工具(jar.exe)等
7.JDK的下载和安装
下载:官网http://www.oracle.com,选择对应的系统和版本即可,java长期支持版本为7,8,11,17,21
7.1安装的细节
1.安装路径不要有中文或者特殊符号如空格等
2.提示安装JRE,建议安装上,且不能和JDK安装目录相同,否则可能会出现plesae ensure JAVA_HOME point to JDK rather JRE
7.2可能出现的问题
在同一台机器上安装多个版本jdk,修改环境变量不生效
原因:因为在安装JDK时,自动将java.exe、javaw.exe、javaws.exe三个可执行文件复制到了C:\Windows\System32目录,由于这个目录在WINDOWS环境变量中的优先级高于JAVA_HOME设置的环境变量优先级
7.3验证安装是否成功
在bin目录下打开命令行测试java,javac
8.JDK安装路径下的目录解释
bin目录:该目录用于存放一些可执行程序
db目录:db目录是一个小型的数据库
jre目录:Java程序运行时环境。此目录是Java运行时环境的根目录,它包括Java虚拟机,运行时的类包,Java应用启动器以及一个bin目录,但不包含开发环境中的开发工具
include目录:由于JDK是通过C和C++实现的,因此在启动时需要引入一些C语言的头文件,该目录就是用于存放这些头文件的
lib目录:lib是library的缩写,意为 Java 类库或库文件,是开发工具使用的归档包文件
src.zip文件:src.zip为src文件夹的压缩文件,src中放置的是JDK核心类的源代码,通过该文件可以查看Java基础类的源代码
9.path环境变量的作用及配置方式
作用:配置后可以在不同的盘符下访问path路径下的可执行文件(bin),如果不配置path则要在bin目录下开发,这显然不合适
配置方法:
1.使用JAVA_HOME配置JDK安装目录
2.Path配置%JAVA_HOME%\bin,这样修改JDK路径时不需要修改Path,防止一些误操作
10.classpath环境变量的作用及其配置
作用:配置访问的类文件的路径,1.5以后默认是当前路径,即编译后生成.class文件的路径,即在哪生成就去找,因此1.5以后不需要配置
弊端:想要执行就必须放到配置路径下,不符合实际需求
配置方法:系统变量中配置classpath,当前路径指的是.
二、语法
1.常量
1.常量定义:在程序执行的过程中其值不可以发生改变
1.常量的分类
字面值常量
字符串常量 用双引号括起来的内容,"zhangsan"
整数常量 所有整数,123
小数常量 所有小数,1.23
字符常量 用单引号括起来的内容,里面只能放单个数字,单个字母或单个符号,'z'
布尔常量 较为特殊,只有true和false
空常量 null(数组部分讲解)
2.变量
1.变量定义:在程序执行的过程中,在某个范围内其值可以发生改变的量
2.变量的定义格式:数据类型 变量名 = 变量值;
3.作用:用来存放同一类型的常量,并可以重复使用
4.注意
1.作用域问题:同一个区域不能使用相同的变量名
2.初始化值问题:局部变量在使用之前必须赋值
3.一条语句可以定义多个变量:int a,b,c...;
int a = 1;
3.标识符
1.标识符定义:给类,接口,方法,变量等命名时使用的字符序列
2.标识符的组成规则:英文大小写字母,数字字符,$和_
3.注意
1.不能使用关键字
2.不能数字开头,但$和_可以,如_123,$123
4.开发中约定俗成的命名规则
见名知意,不用拼音,不写一半的单词
包最好是域名倒过来,所有的字母小写 cn.gtmap
类或者接口:名称为单个单词,首字母大写;名称为多个单词,每个单词首字母大写(驼峰标识)
方法或者变量:单个单词全部小写;多个单词,从第二个单词首字母大写
常量:单个单词,所有字母大写;多个单词,所有的字母大写,用下划线区分每个单词,这样可以区分多个单词,方便阅读理解
int a = 1; //这里的a就是标识符
4.关键字
1.关键字:被Java语言赋予特定含义的单词
2.关键字的特点:组成关键字的字母全部小写
3.常见关键字:public static void class
4.注意:goto和const作为保留字存在,jdk8以前并不使用
5.注释
1.作用:提高阅读性
2.分类
1.单行注释:双斜杠,可以嵌套,//注释1//注释2
2.多行注释:不可以嵌套,会把第一个结束标志视为注释结束,/*注释*/
3.文档注释,可以用来制作说明书
通过javadoc命令生成说明书
@author(提取作者内容)
@version(提取版本内容)
@param 参数名称//形式参数的变量名称@return 函数运行完返回的数据
javadoc -d 指定的文件目录 -author -version ArrayTool.java
6.数据类型
1.数据为什么要分类型
Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存中分配不同大小的内存空间
存储结构不同,针对不同的数据采用适合的存储方式
2.数据类型的分类
基本数据类型(4类8种)
整数型
byte 占一个字节 -128到127
short 占两个字 -2^15~2^15-1
int 占四个字节 -2^31~2^31-1
long 占八个字节 -2^63~2^63-1
浮点型
float 占四个字节 -3.403E38~3.403E38 单精度
double 占八个字节 -1.798E308~1.798E308 双精度
1位符号位 8位指数位 23位尾数位
1 23 52
取值范围主要看指数部分:
float的指数部分有8bit(2^8),由于是有符号型,所以得到对应的指数范围0-255
实际的取值要减去偏移量127,去除全0全1,减去偏移量127,得到-126-127
double的指数部分有11bit(2^11),由于是有符号型,所以得到对应的指数范0-2048
去除全0全1,减去偏移量1023,得到-1022-1023
精度(有效数字)主要看尾数位
单纯的比较两个数字0和0.0是相等的
字符型
char,占两个字节 0~65535
Java语言中的字符char可以存储一个中文汉字,因为Java语言采用的是Unicode编码,每个char占用两个字节,汉字两个字节,所以Java中的字符可以存储一个中文汉字
布尔型
boolean理论上是占八分之一个字节,因为一个开关就可以决定是true和false了,但是java中boolean类型没有明确指定他的大小
boolean是基本数据类型,Boolean是它的封装类,和其他类一样,有属性有方法,可以new
jdk5+,Boolean在"赋值"和判断上和boolean一样
引用数据类型:对象,数组
3.数据类型转换
1.隐式转换
Java中的默认转换规则
进行混合运算的时候,byte,short,char不会相互转换,都会自动类型提升为int类型
其他类型进行混合运算的是小的数据类型提升为大的
byte a = 1;
short b = 1;
int c = a + b; //a+b的结果是int类型
2.强制转换
强制转换的格式:b = (byte)(a + b);//类型也要加括号
强制转换的注意事项:如果超出了被赋值的数据类型的取值范围,数据会被按位截断
int a = 999999999;
short b = (short)a;
System.out.println(b); //输出结果是-13825
3.字符和字符串运算
System.out.println('a'); a字符
System.out.println('a'+1); 98,char和int运算,提升为int
System.out.println("hello"+'a'+1); helloa1
System.out.println('a'+1+"hello"); 98hello
//任何数据类型用+与字符串连接,都会产生新的字符串
System.out.println("5+5="+5+5); 5+5=55
System.out.println(5+5+"=5+5"); 10=5+5
7.运算符
运算符:对常量和变量进行操作的符号
运算符分类:算术运算符,赋值运算符,比较运算符,逻辑运算符,位运算符,三目(元)运算符
算术运算符
算术运算符:+,-,*,/,%,++,--
+:正号,加法运算,字符串连接符
/:获取除法操作的商,整数相除只能得到整数,即会截断结果,如果想得到小数,必须把数据变化为浮点数类型
%:获取除法操作的余数
1.当左边的绝对值小于右边绝对值时,结果是左边;当左边的绝对值等于右边或是右边的倍数时,结果是0;当左边的绝对值大于右边绝对值时,结果是余数
2.%运算符结果的符号只和左边有关系,与右边无关,java中负数取模规则:先忽略负号进行运算,然后符号与被取模数保持一致
(-10)%3==-1;
10%(-3)==1;
(-10)%(-3)==-1;
3.任何一个正整数%2结果不是0就是1,这可以用来当作切换条件
++,--:自增自减,对原有的数据进行+1,-1
++,--注意:
单独使用:放在操作数的前面和后面效果一样
参与运算使用:
放在操作数的前面,先自增或者自减,然后再参与运算
放在操作数的后面,先参与运算,再自增或者自减
举例1
int a = 10;
int b = 10;
int c = 10;
a = b++; a=10,b=11,c=10
c = --a; a=9,b=11,c=9
b = ++a; a=10,b=10,c=9
a = c--; a=9,b=10,c=8
举例2
int x = 4;
int y = (x++)+(++x)+(x*10); //4 + 6 + 6*10 = 70
举例3
byte b = 10;
b++; //自增自减运算符,拓展赋值运算符会做自动强转,不会出错
b = b + 1; //报错
赋值运算符
基本的赋值运算符:=,把=右边的数据赋值给左边
扩展的赋值运算符:+=,-=,*=,/=,%=
+=:把左边和右边做加法,然后赋值给左边
举例
short s = 1;
s = s+1 //这样是不行的,因为s+1会被自动提升为int类型
short s = 1;
s += 1; //这样可以,拓展赋值运算会自动强转,s= (short)(s+1)
关系运算符
关系运算符:==,!=,>,>=,
注意:无论你的操作是简单还是复杂,结果是boolean类型
逻辑运算符
逻辑运算符:&,|,^,!,&&,||
&逻辑与:有false则false
|逻辑或:有true则true
^逻辑异或:相同为false,不同为true
!逻辑非:非false则true,非true则false
注意
逻辑运算符一般用于连接boolean类型的表达式或者值
表达式:就是用运算符把常量或者变量连接起来的符合java语法的式子
算术表达式:a + b
比较表达式:a == b(条件表达式)
&&和&,||和|的区别
最终结果一样
&&具有短路效果,左边是false,右边不执行
&是无论左边是false还是true,右边都会执行
if (a<b && b<c) { //只要a<b不成立,就不会再去看b<c正确与否
...
}
位运算符
位运算符:&,|,^,~,>>,>>>,
&:有0则0,0==false
|:有1则1,1==true
^:相同则0,不同则1,一个数据对另一个数据位异或两次,该数本身不变,可以用来加密解密
~:按位取反
>>:右移,左边补最高位
>>>:无符号右移,左边补0
举例1:两个整数变量的交换
x = x ^ y;
y = x ^ y;
x = x ^ y;
举例2:最有效率的算出2 * 8的结果
2<<3; 直接操作二进制效率是最高的
三元运算符
三元运算符:(关系表达式) ? 表达式1 : 表达式2;
关系表达式结果为true,执行表达式1,否则执行表达式2
举例:获取3个数中最大数
(x>y?(x>z?x:z):(y>z?y:z))
8.流程控制语句
顺序结构
选择结构
if语句
if(比较表达式1) {
语句体1;
}else if(比较表达式2) {
语句体2;
}else if(比较表达式3) {
语句体3;
}
...
else {
语句体n+1;
}
注意事项
1.最后一个else可以省略,但是建议不要省略,可以对范围外的错误值提示
2.语句体只有1句时,大括号可以省略,但建议不省略,因为会有陷阱,如
int x = 10;实际上是2句
int x;
x = 10;
if 语句嵌套
//判断3个数中最大值
private static int selectMax(int x, int y, int z) {
int max;
if (x > y) {
if (x > z) {
max = x;
} else {
max = z;
}
} else {
if (y > z) {
max = y;
}else {
max = z;
}
}
return max;
}
if语句和三元相互转换
三元运算符实现的,都可以采用if语句实现,反之不成立
原因:因为三元运算符是一个运算符,运算符操作完毕就应该有一个结果,而不仅仅是一个输出,因此当if语句控制的操作是一个输出语句的时候就不能用三元运算符替换
switch语句
switch(表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
…
default:
语句体n+1;
break;
}
注意
1.表达式可以是 byte short char int String 枚举,1.7以前不支持String类型
2.default可以省略,但建议不省,可以对错误情况做出说明,default不放在最后也是最后不匹配才去执行,但建议放在最后
3.最后一个break可以省略,但建议不省
4.结束条件是break或者末尾的大括号,而不是执行完default,即所谓的break穿透
5.switch在判断固定值时使用,if往往应用于区间
6.注意多个case对应同一处理的情况,如下
//berak穿透
int x = 2;
int y = 3;
switch(x){
default:
y++;
case 3:
y++;
case 4:
y++;
}
System.out.println("y="+y); //6
switch (x) {
case 1:
case 2:
case 3:
System.out.println("春");
break;
case 4:
case 5:
case 6:
System.out.println("夏");
break;
case 7:
case 8:
case 9:
System.out.println("秋");
break;
case 10:
case 11:
case 12:
System.out.println("冬");
break;
default:
break;
}
举例1
int x = 1,y = 1;
if(x++==2 & ++y==2) // 2 2
{
x =7;
}
System.out.println("x="+x+",y="+y);
x=2,y=2
举例2
int x = 1,y = 1;
if(x++==2 && ++y==2) //2 1
{
x =7;
}
System.out.println("x="+x+",y="+y);
x=2,y=1
举例3
int x = 1,y = 1;
if(x++==1 | ++y==1) //2 2
{
x =7; //7 2
}
System.out.println("x="+x+",y="+y);
x=7,y=2
举例4
int x = 1,y = 1;
if(x++==1 || ++y==1) //2 1
{
x =7; //7 1
}
System.out.println("x="+x+",y="+y);
x=7,y=1
循环结构
循环结构:for,while,do...while
for
//for
for(初始化表达式;条件表达式;循环后的操作表达式) {
循环体;
}
//增强for,集合中常用
for(接收数组元素的变量:循环对象-数组/集合) {
...//语句
}
for (int i =1;i<10;i++) {
System.out.println("*");
}
执行过程
a:执行初始化语句
b:执行判断条件语句,看其返回值是true还是false
如果是true,就继续执行
如果是false,就结束循环
c:执行循环体语句;
d:执行循环后的操作表达式
e:回到b继续
注意
1.判断条件语句无论简单还是复杂结果是boolean类型
2.循环体语句如果是一条语句,大括号可以省略,建议不省
while
初始化语句;
while(判断条件语句) {
循环体语句;
控制条件语句;
}
int i = 1;
while (i< 10) {
System.out.println("*");
}
执行流程:
a:执行初始化语句
b:执行判断条件语句,看其返回值是true还是false
如果是true,就继续执行
如果是false,就结束循环
c:执行循环体语句;
d:执行控制条件语句
e:回到B继续
do...while
初始化语句;
do {
循环体语句;
控制条件语句;
}while(判断条件语句);
int i = 1;
do {
System.out.println("*");
} while (i > 10);
//虽然条件i>10不成立,但循环体在进行条件判断之前就已经执行了一次
执行流程:
a:执行初始化语句
b:执行循环体语句
c:执行控制条件语句
d:执行判断条件语句,看其返回值是true还是false
如果是true,就继续执行
如果是false,就结束循环
e:回到b继续
几种循环的区别
1.do...while循环至少执行一次循环体
2.for循环结束后,循环控制变量从内存中弹出,while循环的控制变量在while外声明,不随其弹出,但这样的情况在开发中很少,几乎不用while和do while
循环嵌套
外循环控制行数,内循环控制列数
乘法表
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + " * " + i + " = " + (i*j) +"\t");
}
System.out.println();
}
'\x' x表示任意,\是转义符号,这种做法叫转移字符
'\t' tab键的位置
'\r' 回车
'\n' 换行
'\"'
'\''
死循环
当循环条件恒成立
while(true){...}
for(;;){...}
控制跳转语句
break switch 和 循环 中,终止
continue 循环中,跳出当次循环
return 借由结束方法的方式结束循环
//举例
for(int x=1; x<=10; x++) {
if(x%3==0) {
//在此处填写代码
}
System.out.println(“Java”);
}
在控制台输出2次:"Java" break;
在控制台输出7次:"Java" continue;
在控制台输出13次:"Java" System.out.println("Java基础")
控制跳转语句标号(实际开发不用,不重要)
标号:标记某个循环对其控制
标号组成规则:合法的标识符
//outer就是标号,只要是合法的标识符即可
outer: for (int i = 1;i <= 10 ;i++ ) {
System.out.println("i = " + i);
inner: for (int j = 1;j <= 10 ;j++ ) {
System.out.println("j = " + j);
//标号一般用于跳出外部循环,break和break inner没什么区别,都是跳出本次循环
break outer;
}
}
9.方法
方法:完成特定功能的代码块
方法作用:提高代码的复用性
方法定义格式
public int getMax(int a, int b) {
return a > b ? a : b;
}
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {
方法体语句;
return 返回值;
}
说明
修饰符:目前就用 public
返回值类型:功能结果的数据类型
方法名:符合命名规则即可
参数:
实际参数:实际参与运算的
形式参数;方法定义上的,用于接收实际参数
参数类型:参数的数据类型
参数名:变量名
方法体语句:完成功能的代码
return:给定方法返回值,会立刻结束方法
返回值:功能的结果,由return带给调用者,如果方法有明确的返回值,一定要有return带回一个值
注意
方法与方法是平级关系,不能嵌套定义
方法定义的时候参数之间用逗号隔开
方法调用
方法不调用不执行
怎么调用:方法名+给定入参,方法调用的时候不用再传递数据类型
有返回值的调用:用变量接收方法返回值,或者结果作为其他操作的参数
方法调用--参数传递
基本数据类型值传递不改变原值,因为方法调用后就会弹栈,局部变量随之消失
引用数据类型值传递会改变原值,因为即使方法弹栈,但实际改变的是堆内存中的数据,数组对象还在,仍可以通过地址访问
public static void main(String[] args) {
int a = 1;
int b = 2;
int res = getMax(a, b);
System.out.println(a); //1
System.out.println(b); //2,a和b的值并不会因为getMax中进行的操作被改变
System.out.println(res); //3,getMax接收到1,2后,方法内进行的运算会影响1,2的值
SpringApplication.run(CrmApplication.class, args);
}
public static int getMax(int a, int b) {
a++;
b++;
return a > b ? a : b;
}
方法重载
定义:同一个类中,方法名相同,参数列表不同(个数,类型,顺序-算重载,但是在开发中不用),与返回值类型无关
举例:求和方法,同名,但参数列表不同(两个整数,两个浮点数...)
public int getMax(int a, int b) {
a++;
b++;
return a > b ? a : b;
}
public int getMax(double a, double b) {
a++;
b++;
return a > b ? a : b;
}
main方法
格式:public static void main(String[] args) {}
public:被jvm调用,访问权限足够大
static:被jvm调用,不用创建对象,直接类名访问
void:被jvm调用,不需要给jvm返回值
main:一个通用的名称,虽然不是关键字,但是被jvm识别
String[] args:以前用于接收键盘录入的
可变参数
定义方法的时候不知道该定义多少个参数
格式:修饰符 返回值类型 方法名(数据类型… 变量名){}
注意事项
这里的变量其实是一个数组
如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个,否则,前面的实参会尽可能的被可变形参接收
public static void sout(int...a) {
System.out.println(a);
}
public static void sout(int a, int b, int...c) {
System.out.println(a);
System.out.println(b);
System.out.println(c);
}