目录
前言
一、java基础
1.1概述
1.java语言发展史
2.Java语言版本
3.Java语言平台
4.Java语言特点
5.Java语言跨平台原理-可移植性
6.JRE和JDK的概述
7.JDK的下载和安装
8.JDK安装路径下的目录解释
9.path环境变量的作用及配置方式
10.classpath环境变量的作用及其配置
1.2语法
1.常量
2.变量
3.标识符
4.关键字
5.注释
6.数据类型
7.运算符
算术运算符
赋值运算符
关系运算符
逻辑运算符
位运算符
三元运算符
8.流程控制语句
顺序结构
选择结构
if语句
switch语句
循环结构
for
while
do...while
几种循环的区别
循环嵌套
死循环
控制跳转语句
1.3.方法
方法调用--参数传递
方法重载
1.4数组
数组的初始化
数组的内存分配
二维数组(实际开发几乎不用)
二、面向对象
2.1概述
2.2类与对象
2.3成员变量,局部变量,构造方法
2.4封装,继承,多态
2.5static,final
2.6抽象类,接口
2.7权限修饰符
2.8成员内部类
三、集合框架
3.1概述
3.2List
3.3Set
3.4Map
四、异常
五、IO流
六、多线程
七、反射
前言
整理一下多年之前学习javaSE的笔记,将会包括java基础,对象,集合,异常,IO流,多线程,反射
一、java基础
1.1概述
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
安装的细节:
1.安装路径不要有中文或者特殊符号如空格等
2.提示安装JRE,建议安装上,且不能和JDK安装目录相同,否则可能会出现plesae ensure JAVA_HOME point to JDK rather JRE
可能出现的问题
在同一台机器上安装多个版本jdk,修改环境变量不生效
原因:因为在安装JDK时,自动将java.exe、javaw.exe、javaws.exe三个可执行文件复制到了C:\Windows\System32目录,由于这个目录在WINDOWS环境变量中的优先级高于JAVA_HOME设置的环境变量优先级
验证安装是否成功:在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.2语法
1.常量
1.常量:在程序执行的过程中其值不可以发生改变
2.常量的分类
字面值常量
字符串常量 用双引号括起来的内容
整数常量 所有整数
小数常量 所有小数
字符常量 用单引号括起来的内容,里面只能放单个数字,单个字母或单个符号
布尔常量 较为特殊,只有true和false
空常量 null(数组部分讲解)
自定义常量
2.变量
1.变量:在程序执行的过程中,在某个范围内其值可以发生改变的量
2.变量的定义格式:数据类型 变量名 = 变量值;
3.作用:用来存放同一类型的常量,并可以重复使用
4.注意
1.作用域问题:同一个区域不能使用相同的变量名
2.初始化值问题:局部变量在使用之前必须赋值
3.一条语句可以定义多个变量:int a,b,c...;
3.标识符
1.标识符:给类,接口,方法,变量等命名时使用的字符序列
2.标识符的组成规则:英文大小写字母,数字字符,$和_
3.注意
1.不能使用关键字
2.不能数字开头,但$和_可以,如_123,$123
4.开发中约定俗成的命名规则
见名知意,不用拼音,不写一半的单词
包最好是域名倒过来,所有的字母小写 cn.gtmap
类或者接口:名称为单个单词,首字母大写;名称为多个单词,每个单词首字母大写(驼峰标识)
方法或者变量:单个单词全部小写;多个单词,从第二个单词首字母大写
常量:单个单词,所有字母大写;多个单词,所有的字母大写,用下划线区分每个单词,这样可以区分多个单词,方便阅读理解
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
boolean理论上是占八分之一个字节,因为一个开关就可以决定是true和false了,但是java中boolean类型没有明确指定他的大小
boolean是基本数据类型,Boolean是它的封装类,和其他类一样,有属性有方法,可以new
jdk5+,Boolean在"赋值"和判断上和boolean一样
引用数据类型:对象,数组
3.数据类型转换
1.隐式转换:Java中的默认转换规则
进行混合运算的时候,byte,short,char不会相互转换,都会自动类型提升为int类型
其他类型进行混合运算的是小的数据类型提升为大的
2.强制转换
强制转换的格式:b = (byte)(a + b);//类型也要加括号
强制转换的注意事项:如果超出了被赋值的数据类型的取值范围得到的结果会与你期望的结果不同
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.运算符
运算符:对常量和变量进行操作的符号
运算符分类:算术运算符,赋值运算符,比较运算符,逻辑运算符,位运算符,三目(元)运算符
算术运算符
算术运算符:+,-,*,/,%,++,--
功能
+:正号,加法运算,字符串连接符
/:获取除法操作的商:整数相除只能得到整数,即会截断结果,如果想得到小数,必须把数据变化为浮点数类型
%:获取除法操作的余数
当左边的绝对值小于右边绝对值时,结果是左边;当左边的绝对值等于右边或是右边的倍数时,结果是0;当左边的绝对值大于右边绝对值时,结果是余数
%运算符结果的符号只和左边有关系,与右边无关,java中负数取模规则:先忽略负号进行运算,然后符号与被取模数保持一致
(-10)%3==-1; 10%(-3)==1; (-10)%(-3)==-1;
任何一个正整数%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;
short s=1;
s+=1; 拓展赋值运算会自动强转,s= (short)(s+1)
关系运算符
关系运算符:==,!=,>,>=,
注意:无论你的操作是简单还是复杂,结果是boolean类型
逻辑运算符
逻辑运算符:&,|,^,!,&&,||
注意
逻辑运算符一般用于连接boolean类型的表达式或者值
表达式:就是用运算符把常量或者变量连接起来的符合java语法的式子
算术表达式:a + b
比较表达式:a == b(条件表达式)
功能:
&逻辑与:有false则false
|逻辑或:有true则true
^逻辑异或:相同为false,不同为true
!逻辑非:非false则true,非true则false
特点:偶数个不改变本身
&&和&,||和|的区别
最终结果一样
&&具有短路效果,左边是false,右边不执行
&是无论左边是false还是true,右边都会执行
位运算符
位运算符:&,|,^,~,>>,>>>,
功能
&:有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;
举例:获取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(接收数组元素的变量:循环对象-数组/集合) {
...//语句
}
执行过程
a:执行初始化语句
b:执行判断条件语句,看其返回值是true还是false
如果是true,就继续执行
如果是false,就结束循环
c:执行循环体语句;
d:执行循环后的操作表达式
e:回到b继续
注意
1.判断条件语句无论简单还是复杂结果是boolean类型
2.循环体语句如果是一条语句,大括号可以省略,建议不省
while
初始化语句;
while(判断条件语句) {
循环体语句;
控制条件语句;
}
执行流程:
a:执行初始化语句
b:执行判断条件语句,看其返回值是true还是false
如果是true,就继续执行
如果是false,就结束循环
c:执行循环体语句;
d:执行控制条件语句
e:回到B继续
do...while
初始化语句;
do {
循环体语句;
控制条件语句;
}while(判断条件语句);
执行流程:
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;
}
}
1.3.方法
方法:完成特定功能的代码块
方法作用:提高代码的复用性
方法定义格式
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {
方法体语句;
return 返回值;
}
说明
修饰符:目前就用 public static。后面我们再详细的讲解其他的修饰符
返回值类型:就是功能结果的数据类型
方法名:符合命名规则即可。方便我们的调用
参数:
实际参数:就是实际参与运算的
形式参数;就是方法定义上的,用于接收实际参数的
参数类型:就是参数的数据类型
参数名:就是变量名
方法体语句:就是完成功能的代码
return:结束方法
返回值:就是功能的结果,由return带给调用者,如果方法有明确的返回值,一定要有return带回一个值
注意
方法与方法是平级关系,不能嵌套定义
方法定义的时候参数之间用逗号隔开
方法调用
方法不调用不执行
怎么调用:方法名+给定入参,方法调用的时候不用再传递数据类型
有返回值的调用:用变量接收方法返回值,或者结果作为其他操作的参数
方法调用--参数传递
基本数据类型值传递不改变原值,因为方法调用后就会弹栈,局部变量随之消失
引用数据类型值传递会改变原值,因为即使方法弹栈,但实际改变的是堆内存中的数据,数组对象还在,仍可以通过地址访问
方法重载
定义:同一个类中,方法名相同,参数列表不同(个数,类型,顺序-算重载,但是在开发中不用),与返回值类型无关
举例:求和方法,同名,但参数列表不同(两个整数,两个浮点数...)
1.4数组
数组:存储同一种数据类型多个元素的集合
数组作用:存储同种数据类型的多个值,可以存储基本数据类型,引用数据类型
数组定义格式:
数据类型[] 数组名 = new 数据类型[数组的长度];
int[] arr = new int[5];
数组的初始化
初始化时,为数组开辟连续的内存空间,并为每个数组元素赋值
动态初始化
只指定长度,由系统给出初始化值(默认值)
数据类型[] 数组名 = new 数据类型[数组长度];
int[] arr = new int[5];
整数类型 byte,short,int,long 默认为0
浮点类型 float,double 默认为0.0
布尔类型 boolean 默认false
字符类型 char 默认为'\u0000' \u是转义字符意为Unicode编码
char是2个字节,16位二进制值,即4位16进制0
在内存中开辟一块连续的空间(地址值赋值给数组变量)
Sop(arr)输出类型和哈希值 [I@... int型一 维数组
静态初始化
给出初始化值,由系统决定长度
初始化的时候,仍然先进行默认初始化(0),然后才进行显式初始化
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,…};
数据类型[] 数组名 = {元素1,元素2,…};
数组的内存分配
Java中的内存分配
栈:存储局部变量,方法
堆:存储new出来的数组或对象
方法区
本地方法区:系统相关
寄存器:给CPU使用
数组的内存分配
声明一个数组,会在栈中生成一个数组变量,变量指向堆中new出来的数组实例
当然可以在栈中声明多个数组变量,指向堆中的同一个数组实例
数组的角标
数组元素具有索引角标,从0开始计数,访问不存在的角标时,会报ArrayIndexOutOfBoundsException
数组的基本操作
//遍历
for (int i = 0;i < arr.length ;i++ ) {
System.out.print(arr[i] + " ");
}
//查找
for (int i = 0;i < arr.length ;i++ ) {
if (arr[i] == value) {
return i;
}
}
二维数组(实际开发几乎不用)
格式:
int[][] arr = new int[3][2];
int[][] arr = new int[3][];
int[][] arr = {{1},{2,3},{4,5,6}};
内存分配
栈中声明的二维数组变量,先指向一个一维数组,这个一维数组的每个元素,又分别指向一个一维数组,每个一维数组就是一行
二维数组基本操作
int[][] arr = {{1,2,3},{4,5},{6,7,8,9}};
for (int i = 0;i < arr.length ;i++ ) {//遍历第一层的一维数组
for (int j = 0;j < arr[i].length ;j++ ) {//获取第一层数组元素指向的多个一维数组中的元素
System.out.print(arr[i][j] + " ");
}
System.out.println();
}