JavaSE学习笔记
序
在之前的寒假和现在的暑假一直在看黑马程序员的JavaSE教程,但随着时间的流逝以及期末考试期间没有对java进行练习,使得一些知识都快忘记了,现在通过运用blog记录的方式对平时的内容进行总结,并记录自己技能的增长。附赠Java官方API文档
Java SE
基础
注释
·单行注释://注释信息
·多行注释:/注释信息/
·文档注释:/*注释信息/
常量:程序运行中值不改变的量
- 概述:常量是使用public static final修饰的成员变量,必须拥有初始化值,而且执行的过程中其值不能被改变
- 常量的作用和超出:可以用于做系统的配置信息,方便程序的维护,同时提高可读性
- 常量的命名规范:英文单词全部大写,多个单词下划线连接起来
- 常量的执行原理
- 在编译阶段会进行“宏替换”,把使用常量的地方全部替换成真实的字面量
- 这样做的好处是让使用常量的程序执行性能与直接使用字面量是一样的
- 常量做信息标志和分类:代码可读性好,实现了软编码形式
类型 | 特点 | 范例 |
---|---|---|
字符串常量 | 用双引号括起来的内容 | “HelloWord” |
整数常量 | 不带小数的数字 | 666,-88 |
小数常量 | 带小数的数字 | 13.14,-5.12 |
字符常量 | 用单引号括起来的内容 | ‘A’,‘0’ |
布尔常量 | 布尔值,标志真假 | true,false |
空常量 | 一个特殊的值,空值 | 值是null |
注:只有空常量不能直接输出
变量:在程序运行中可以改变值的量
1.Main中变量名不能重复
2.定义变量一定要赋值,不赋值不能使用
3.long类型报错整数太大,在赋的值后加L
4.浮点数默认为double类型
5.在定义float时,在赋的值后加F
常见命名约定:
- 小驼峰命名法:(针对方法、变量)
- 标识符是一个单词时,首字母小写
- 标识符由多个单词组成时,第一个单词首字母小写,其他单词首字母大写
- 大驼峰命名法:(针对类)
- 标识符是一个单词时,首字母大写
- 标识符由多个单词组成时,每个单词的首字母都大写
算数运算符
·运算符:对常量或者变量进行操作的符号
·表达式:用运算符把常量或者变量连接起来符合java语法的式子就可以称为表达式
·除法(/)得到的商,取余(%)得到的是余数
·整数相除只能得到整数,要想得到小数,必须有浮点数的参与
·算术表达式中包含多个基本数据类型的值的时候,算术表达式的类型会自动提生
·提升规则:
1.byte类型,short类型和char类型将被提升到int类型
2.整个表达式的类型自动提升到表达式中最高等级操作数同样的类型
等级顺序:byte、shor、char->int->long->float->double
逻辑运算符
·&与:a,b结果有false则false
·|或:a,b结果有true则true
·^异或:a,b结果相同为false,不同为true
·!非:!a结果和a的结果相反
短路逻辑运算符
·&&:短路与:和&相同,但有短路效果
·||:短路或:和|相同,但有短路效果
·&:无论左边真假,右边都要执行
·&&:如果左边为真,右边执行,如果左边为假,右边不执行
·|:无论左边真假,右边都要执行
·||:如果左边为假,右边就需要执行,如果左边为真,右边不用执行
最常用的逻辑运算符:&&、||、!
三元运算符:
·格式:关系表达式?表达式1:表达式2
·范例:a>b?a:b
·首先计算关系表达式的值
·如果值为true,表达式1的值就是运算结果
·如果值为false,表达式2的值就是运算结果
数据输入:
Scanner的基本使用步骤:
1.导包:import java.util.Scanner;
导包的动作必须出现在类定义上边,即出现在public class 类名上边
2.创建对象:Scanner sc = new Scanner(System.in);
上面这个格式里,只有sc是变量名,可以变,其他的都不允许变
3.接收数据:int I =sc.nextInt();
上面这个格式里边,只有i是变量名,可以变,其他的都不允许变sc要与上边的sc相同
分支语句
- 流程控制
- 分支结构(if, switch)
- 循环结构(for, whiled…while)
- if语句
- 格式一:if(关系表达式){语句体;}
- 格式二:if(关系表达式){语句体1;}else{语句体2;}
- 格式三:if(关系式表达式1){语句体1;}else if(语句表达式2){语句体2;}…else{语句体n+1;}
- switch语句
- 格式:
switch(){ case "": break; case "": break; default: break; }
- 格式:
循环结构
组成:初始化语句、条件判断语句、循环体语句、条件控制语句
- for语句
- 格式:fou(初始化语句;条件判断语句;条件控制语句){循环语句体;}
- while语句
- 基本格式:while(条件判断语句){循环体语句;}
- 完整格式:初始化语句;while(条件判断语句){循环体语句;条件控制语句;}
- do……while语句
- 基本格式:do{循环体语句;}while(条件判断语句);
- 完整格式:初始化语句;do{循环体语句;条件控制语句;}while(条件判断语句);
- 死循环:
- for语句:For(;;){}表示条件永远为真
- while语句:while(true){}表条件永远为真
- do……while语句:do{}while(true);表条件永远为真
- 一般用while的死循环
- 三种循环的区别:
- for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行
- do…while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
跳转控制语句:
·Continue:用在循环中,基于条件控制,跳过某次循环体内容的执行,继续下一次的执行
·Break:用在循环中,基于条件控制,终止循环体内容的执行,也就是说结束当前的整个循环
产生一个随机数 Random
- 使用步骤:
- 导包:import java.util.Random;
- 创建对象:Random r=new.Random;
- 获取随机数:int number=r.nextInt(10);//获取数据的范围:0-10包括0,不包括10
数组 定义格式
·数据类型[]变量名:int[] arr(推荐)
·数据类型 变量名[]:int arr[]
- 数组初始化:
- 动态初始化:只指定数组长度,由系统进行赋值
- 格式:数据类型[]变量名=new 数据类型[数组长度];
int[] arr=new int[3]; - 静态初始化:指定每个元素都初始值,有系统决定数组的长度
- 格式:数据类型[]变量名=new 数据类型[]{数据1,数据2,数据3,…};
int [] arr=new int[]{1,2,3,…};- 简化格式:数据类型[]变量名={数据1,数据2,数据3,…};
int[] arr={1,2,3};
- 简化格式:数据类型[]变量名={数据1,数据2,数据3,…};
- 数组操作的两个常见的小问题:
- 索引越界:访问了数组中不存在的索引对应的元素,造成索引越界问题
- 空指针异常:访问的数组已经不再指向堆内存的数据,造成空指针异常
- null:空值,引用数据类型的默认值,表示不指向任何有效对象
方法重载
·方法重载的描述:指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载
·多个方法在同一个类中
·多个方法具有相同的方法名
·多个方法的参数不同,类型不同或者数量不同
方法的参数传递
·方法参数传递的基本类型:对于基本数据类型的参数,形式参数的改变,不影响实际参数的值
·方法参数传递的引用类型:对于引用类型的参数,形式参数改变,影响实际参数的值
面向对象基础
类和对象
·类:类是对现实生活中一类具有共同属性和行为的事物的抽象
·对象:对象是能看得到摸得着的真实存在的实体
- 对象:万物皆对象,客观存在的事物皆为对象
- 面向对象:面向一个具体的对象进行草足
- 类:类是对现实生活中一类具有共同属性和行为的事物的抽象
- 类的特点:
- 类是对象的数据类型
- 类是具有相同属性和行为的一组对象的集合
- 对象的属性:对象具有的各种特征,每个对象的每个属性都拥有特定的值
- 对象的行为:对象能够执行的操作
- 类和对象的关系:类是对象的抽象,对象是类的实体
成员变量和局部变量
·成员变量;类中方法外的变量
·局部变量:方法中的变量
·成员变量和局部变量的区别
分类 | 成员变量 | 局部变量 |
---|---|---|
类中位置不同 | 类中方法外 | 方法内或者方法声明上 |
内存中位置不同 | 堆内存 | 栈内存 |
生命周期不同 | 随着对象的存在而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的完毕而消失 |
初始化值不同 | 有默认的初始化值 | 没有默认的初始化值,必须先定义,赋值,才能使用 |
封装
封装概述:
是面向对象三大特征之一(封装、继承、多态)是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的
- private关键字
- 是一个权限修饰符
- 可以修饰成员(成员变量和成员方法)
- 作用是保护成员 不被别的类使用,被private修饰的成员只在本类中才能访问
- 针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
- 提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰
- 提供“set变量名(参数)”方法,用于设置成员变量的值,方法有public修饰
- this关键字
- this修饰的变量用于指代成员变量
- 方法的形参如果与成员变量同名,不带this修饰的变量指的是行参,而不是成员变量
- 方法的形参如果没有与成员变量同名,不带this修饰的变量指的是成员变量
- 什么时候用this:解决局部变量隐藏成员变量
- this代表所在的类的对象引用
- this修饰的变量用于指代成员变量
- 封装原则: 将类的某些信息隐藏在类内部,不允许外部程序之间访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问,成员变量private,提供对应的getXxx()/setXxx()方法
- 封装的好处:
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用方法进行封装,提高了代码的复用性
构造方法
- 构建方法注意事项
- 构造方法的创建
- 如果没有定义构造方法,系统会给出一个默认的无参构造方法
- 如果定义了构造方法,系统将不在提供默认的构造方法
- 构造方法的重载
- 如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参构造方法
- 建议:无论是否使用,都手工书写无参构造方法
- 构造方法的创建
- 标准类制作
- 成员变量:使用pravte修饰
- 构造方法:提供一个无参构造方法、提供一个带参数的构造方法
- 成员方法:提供每一个成员变量对应的setXxx()/getXxx()
- 创建对象并为其成员变量赋值的两种方式
- 无参构造方法创建对象后使用setXxx()赋值
- 使用带参构造方法直接创建带有属性值的对象
字符串
字符串的特点:
- 字符串不可变,他们的值在创建后不能被改变
- 虽然String的值是不可变的,但是他们可以被共享
- 字符串效果相当于字符数组(char[]),但是底层原理是字节数组(byte[])
字符串的比较
·使用“==”做比较:比较的是地址值是否相同
·字符串是对象,它比较内容是否相同,是通过一个方法来实现的,这个方法叫:equals()注:逐一对比Public boolean equals(Object an Object){}:将此字符串与指定对象进行比较。由于我们比较的是字符串对象,所以参数直接传递一个字符串
遍历字符串的通用格式:
for(int i=0;i<s.length();I++){ s.charAt(i);//就是字符串指定索引处的字符值 }
String:
- String描述:String类代表字符串,java程序中的所有字符串文字(如“abc”)都以实现为此类都实例,也就是说,java程序中所有的双引号字符串,都是String类的对象
- String构造方法
- public String():创建一个空白字符串对象,不含邮任何内容
- public String(char[]chs):根据字符数组的内容,来创建字符串对象
- public String(byte[]bys):根据字节数组的内容,来创建字符串对象
- String = “abc”:直接赋值的方式创建字符串对象,内容就是abc
- String对象特点
- 通过new创建的字符对象,每一次new都会申请一个内存空间,虽然内容相同,但地址值不同
- 以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码出现几次,jvm都只会建立一个String对象,并在字符串池中维护
String Builder:字符串拼接
- 特点:
- String Builder是一个可变的字符串类,我们可以把它看成是一个容器,
- 这里的可变指的是String Builder对象中的内容是可变的
- 构造方法
- Public String Builder() 创建一个空白可变字符串对象,不含有任何内容
- public String Builder(String str)根据字符串的内容,来创建可变字符串对象
- Public String Builder(任意类型):添加数据,并返回对象本身
- public String Builder reverse():返回相反的字符序列
实例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import java.util.Scanner;
public class 字符串反转 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入字符串");
String s=sc.nextLine();
//String c=str(s);
String c=ss(s);
System.out.println("s:"+c);
}
public static String ss(String s){
StringBuilder sb=new StringBuilder(s);
sb.reverse();
String ss=new String(sb);
return ss;
}
}
- 特点:
String与String Builder的区别
类型 | 区别 |
---|---|
String | 内容是不可变的 |
String Builder | 内容是可变的 |
String Builder和String相互转换
- String Builder转换为string:
publicStringtoString():通过to String()就可以实现把String Builder转换为String - String转换为String Builder:
public String Builder(String s):通过构造方法就可以把String转换为String Builder
实例:1
2
3
4
5
6
7
8
9
10
11public static void main(String[] args) {
//String Builder转化为String
StringBuilder sb=new StringBuilder();
sb.append("hello");
String s=sb.toString();
System.out.println(s);
//String转换为String Builder
String s="hello";
StringBuilder sb=new StringBuilder(s);
System.out.println(sb);
}
- String Builder转换为string:
更多方法···
·toCharArray()->将字符串拆分返回一个字符数组
·substring(start,end)->从start开始到end截取字符串返回一个新字符串
·replace(“a”,”b”)->将字符串中的a全部替换成b
·split(“,”)->将字符串以”,”分隔,返回一个字符串数组
常用API
API
- API概述
- API(Application Programming Interface):应用程序编程接口
- Java API:指的就是JDK中提供的各种功能的java类
- 这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要信息这些类如何使用即可,我们可以通过帮助文档来信息这些API如何使用
- 如何使用帮助文档
- 右键/双击打开
- 找到索引
- 在索引中的文本框中输入查找内容
- 先看软件包,然后往下看类的描述信息,构造方法,
注:调用方法的时候,如果方法有明确的返回值,我们用变量接收
可以手动完成,也可以使用快捷键的方式完成(Ctrl+Alt+V)
Math
- Math描述(java.lang.MAth)
·基本数字运算方法
·如果是静态,通过类名可直接运用 - Math类的常用方法
方法名 | 说明 |
---|---|
public static int abs(int a) | 返回参数绝对值 |
public static double ceil(double a) | 返回大于或等于参数的最小double值,等于一个整数 |
public static double floor(double a) | 返回小于或等于参数的最小double值,等于一个整数 |
public static int round(float a) | 按四舍五入返回最接近参数的int值 |
public static int max(int a,int b) | 返回两个int中较大的值 |
public static int min(int a,int b) | 返回两个int中较小的值 |
public static double pow(double a,double b) | 返回a的b次幂的值 |
Public static double random() | 返回值为double的正值,[0.0,1.0) |
强转位int类型((int)(Math.random()*100))
System(不能被实例化)
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行的java虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |
返回当前时间于1971年1月1日0点的毫秒值
Object
方法名 | 说明 |
---|---|
equals() | 比较两个对象内容是否相等 |
Arrays
- 排序:sort()按数字顺序排序数组
·格式:Arrays.sort(数组名) - 换为字符串输出:toString()
·格式:Arrays.toString(数组名) - 二分搜索技术(数组必须排好序,不然出bug):
·binarySearch(数组名,搜索元素 )
找到返回索引,找不到返回-(应该插入位置的索引+1)
工具类的设计思想
·构造方法用private修饰
·成员用public static修饰
基本类型包装类
将基本数据类型封装称对象的好处在于可以在对象中定义更多的功能方法操作该数据
常见操作之一:用语基本数据类型与字符串之间的转换基本数据类型 包装类 byte Byte short Short int Integer long Long float Float double Double char Character boolean Boolean Integer类的概述和使用
Integer:包装一个对象中原始类型int的值方法名 说明 public Integer(int value) 根据int值创建Integer对象(过时) public Integer(String s) 根据String的值创建Integer对象(过时) public static Integer valueOf(int i) 返回指定的int值的Integer实例 Public static Integer valueOf(String s) 返回一个保存指定值的Integer对象String 格式:
·Integer i1=Integer.valueOf();(用于int)
·Integer i2=Integer.valueOf();(用语String)int和String的相互转换
- int转String
- 方式一:
·int number =100;
·String s1=“”+number; - 方式二:public static String valueOf(int i):
·String s2=String.valueOf(number);
- 方式一:
- String转int
- 方式一:
·String s=“100”;
·Integer I=Integer.valueOf(s);
·int x=intValue();
- 方式一:
- 方式二:public static int parseInt(String s):
·int y=Integer.parseInt();
- int转String
split:将一个大字符串分成小字符串
装箱&拆箱
·装箱;把基本数据类型转换为对应的包装类类型
·拆箱:把包装类类型转换为对应的基本数据类型
- 装箱
- In tiger I =Integer.valueOf(整型);-(手动)
- Integer ii=整型—(自动装箱)
- 拆箱
- .intValue()-(手动)
- ii+=200(自动拆箱)
注:在使用包装类类型的时候,如果做操作,最好先判断是否为null
推荐:只要是对象,在使用前就你许进行不为null的判断
Date类
Date代表了一个特定的时间,精确到毫秒
方法名 | 说明 |
---|---|
public Date() | 分配一个Date对象,并初始化,以便它代表它被分配到时间,精确到毫秒 |
public Date(Long date) | 分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 |
步骤:
先导包:
·import java.util.Date;
·Date d1=new Date()
·返回d1为当前时间常用方法
方法名 说明 public long getTime() 获取的是日期对象从1970年1月1日00:00:00到现在的毫秒值 public void setTIme(long tine) 设置时间,给的是毫秒值 getTime() 返回与1970.1.1零时距今的毫秒值
·long time=60006060-设置时间
·地址符.setTime(time)-调用设定时间
SimpleDateFormat
- 概述:
- SimpleDateFormat是一个具体的类,用语以区域设置敏感的方式格式化和解析日期
- 日期和时间格式由日期和时间模式字符串指定,在日期和时间模式字符串中,从“A”到“Z”以及从“a”到“z”引导到字母被解释为表示日期或时间字符串的组件的模式字母
- 常用的模式字母及对应关系;
小Y——年
大M——月
小D——日
大H——时
小M——分
小S——秒 - 构造方法
方法名 | 说明 |
---|---|
public SimpleDateFormat() | 构造一个 SimpleDateFormat,使用默认模式和日期格式 |
public SimpleDateFormat(String pattern) | 构造一个 SimpleDateFormat使用给定的模式和默认时期格式 |
- 格式化(从Date——String)
·format(Date date);将日期格式化成日期/时间字符串 - 解析(从String——Date)
parse(String source);从给定字符串的开始解析文本以及生成日期
注:需要匹配格式
范例:
1 | // 格式化时间 |
Calendar
·Calendar是一个抽象类,不能直接创建对象。
方法:
·get(int field)返回日期某个字段信息(Year、Month、Day)
·set(int field,int value)修改日历的某个字段信息
·add(int field,int amount)为某个字段增/减指定的值
·getTime()拿到此刻日期对象,返回一个Date对象
·getTimeInMillis()拿到此刻时间毫秒值
正则表达matches
- 正则表达式可以用一些规定的自负来制定鬼职责,并用来校验数据格式的合法性。
·Split():按照正则表达式匹配的内容进行区分,返回一个字符串发数组
·replaceAll(String regex,String s):按照正则表达式匹配的内容进行替换 - matches格式:
字符类:
[abc] 指定字符
[^abc] 除了指定字符外的字符
[a-zA-Z] 从a(A)到z(Z)包括
[a-d[m-p]] 从a到d或从m到p
[a-z&&[^def]] d,e或m(交集)
[a-z&&[^bc]] 从a到z,除去b和c
[a-z&&[^m-p]] 从a到z,除去m到p字符
预定义字符:
. 任何字符
\d 一个数字[0-9]
\D 非数字[^0-9]
\s 一个空白字符[\t\n\x0B\f\r]
\S 非空白字符[^\s]
\w 英文、数字、下划线[a-zA-Z_0-9]
\W 一个非单词字符[^\w]
贪婪量词:
X? x,一次或无
x* x,0次或多次
x+ x,一次或多次
x{n} x,n次
x[n,] x,至少n次
x[n,m] x,至少n不超过m
public boolean matches(String regex):
判断是否匹配正则表达式,匹配返回true

11.3爬取
1 | 范例: |
内部类
- 内部类概述
在一个类中定义一个类
举例:在一个类A的内部定义一个类B,类B就被称为内部类
格式:1
2
3
4public class 类名{
修饰符(public/private) class 类名{
}
}
注:内部类一般为私有(private)
2. 内部类的访问特点
1. 内部类可以直接访问外部类的成员,包括私有
2. 外部类药访问内部类成员,必须创建对象
3. 成员内部类
创建内部类对象格式:
外部类名.内部类名 对象名=外部类对象.内部类对象;(用于公有public)
范例:
Outer.Inner io=new Outer().Inner();
注:不能直接调用私有内部类,但可以同步外部类简介调用内部类
4. 局部内部类
·局部内部类是在方法中定义的类,所有外界 无法直接使用,需要在方法内部创建对象并使用
·该类可以直接访问外部类的成员,也可以访问方法内的局部变量
5. 匿名内部类(局部内部类的特殊形式)
前提:存在一个类或接口,这里边的类可以是具体类也可以是抽象类
格式:
new类名或接口名(){
方法重写;
};
本质:是一个继承了该类或者实现了该接口的子类匿名对象
多次调用可按多态方式进行多次使用
例如:
Inter i=new Inter(){方法重写};
调用时用i.方法名即可;
6. 匿名内部类在开放中的使用
接口无法直接实例化,可运用匿名内部类解决
例如:
jo.nethod(new 接口名(本来为接口实例化)(){重写方法});
Lambda
概述
作用:简化匿名内部类的代码写法
只能简化函数接口的匿名内部类(只能有一个方法)
格式:
(匿名内部类被重写方法的形参列表)->{被重写方法的代码}
范例:1
2
3
4
5
6
7
8
9
10
11public class Lambad1 {
public static void main(String[] args) {
run r=() ->{
System.out.println("wp2002");
};
s.run();
}
}
interface running{
void run();
}Lambda表达式的简化规则
1.参数类型 可以不写
2.如果只有一个参数,参数类型可以省略
3.lambda表达式的方法体代码只有一行,可以省略大括号不写,同时要省略分号
4.lambda表达式的方法体代码只有一行,可以省略大括号不写,此时,如果这行代码是return语句,必须省略return不写,同时也必须省略“;”
继承
- 继承概述
继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法 - 继承的格式
格式:
·public class 子类名 extends父类名{}
范例:
Fu:父类,也称基类、超类public class Zi extends Fu {}
Zi:是子类,也被称为派生类
子类可以有父类的内容,还可以有自己的内容 - 继承的好处
提高了代码的复用性(多个类相同的成员可以放到同一个类中)
提高了代码的维护性(如果方法的代码需要修改,修改一处即可) - 继承的弊端
继承让类与类之间产生了关系,类的耦合性增强类,当父类发生变化时子类的实现也不得不跟着变化,削弱了子类的独立性 - 什么时候使用继承
继承体现的关系:is a
假设法:我有两个类A和B,如果他们满足A是B的一种,或者B时A的一种, 说明他们存在继承的关系,这个时候就可以考虑使用继承来体现,否则就 不能滥用继承
举例:苹果和水果,猫和动物 - 继承中变量的访问特点
- 在子类方法中访问变量
- 子类局部范围找
- 子类成员范围找
- 父类成员范围找
- 如果都没有就报错(不考虑父类的父类…)
- 在子类方法中访问变量
- super:
Super关键字的用法和this关键字的用法相似
this:代表本类对象的引用
super:代表父类存储空间的标识(可以理解为父类对象的引用)
this | super | |
---|---|---|
访问成员变量 | this.成员变量,访问本类成员变量 | super.成员变量,访问父类成员变量 |
访问构造方法 | this(…),访问本类构造方法 | super(…),访问父类构造方法 |
访问成员方法 | this.成员方法(…),访问本类成员方法 | super.成员方法(…),访问父类成员方法 |
导包
·格式 import 包名.类名
修饰符:
- 权限修饰符
同一个类中 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 | |
---|---|---|---|---|
private(私有) | 可以 | |||
默认 | 可以 | 可以 | ||
protected | 可以 | 可以 | 可以 | |
public | 可以 | 可以 | 可以 | 可以 |
- 状态修饰符
- final (最终)
可修饰成员方法,成员变量,类- 被final修饰的方法叫最终方法,不能被重写
格式
public final void 方法名(){} - 被final修饰的变量不能重新赋值
格式
public final 数据类型 变量名 - 被final修饰的类是最终类,不能有子类继承
格式
public final class 类名{} - 修饰引用类型,地址符不能变,但引用内容可以变
格式:
类名 地址符 =new 类名();
- 被final修饰的方法叫最终方法,不能被重写
- static(静态)
可修饰成员方法,成员变量- 修饰成员变量表示共享,该成员变量被所有对象共享
格式:public static 数据类型 变量名
例如:
public static String university;
例如:
特点:student.university
- 非静态成员方法可以访问静态/非静态成员方法和成员变量
- 静态成员方法只能访问静态成员方法和成员变量
- 修饰成员变量表示共享,该成员变量被所有对象共享
- final (最终)
- 枚举
- 概述
·枚举是java重点一种特殊类型
·枚举的作用:是为了做信息的标注和信息的分类 - 定义格式
修饰符 enum枚举名称{
第一行都是罗列枚举实例的名称
}
例如:1
2
3eunm Season{
SPRING,SUMMER,AUTUMN,WINTER
} - 枚举类的特点
- 枚举类都是继承了枚举类型:java.lang.Enum
- 枚举都是最终类,不可以被继承
- 枚举类的构造器都是私有的,枚举对外不能创建对象
- 枚举类的第一行默认都是落泪枚举对象的名称的
- 枚举类是多列模式
- 枚举的作用
- 选择常量做信息标志和分类:虽然可以实现可读性,但是入参值不受约束,代码相对不严谨
- 枚举做信息标志和分类:代码可读性好,入参约束严谨,代码优雅,是最好的信息分类技术,建议使用
- 概述
多态
- 多态概述:统一对象在不同时刻表现出来的不同形态
- 多态的前提和体现
- 有继承/实现关系
- 有方法重写
- 有父类(引用/接口)指向(子/实现)类对象
例: 动物 animal = new 猫();
- 多态中成员访问特点
成员变量 | 编译看左边,执行看左边 |
---|---|
成员方法 | 编译看左边,执行看右边 |
- 多态中的转型
- 向上转型(父类引用指向子类对象)
格式:父类名 地址符 =new子类名();
- 向下转型(父类引用转为子类对象)
格式:子类名 地址符=(子类名)父类的地址符
- 向上转型(父类引用指向子类对象)
- 多态的形式
具体类多态、抽象类多态、接口多态
抽象类
·方法抽象类必须抽象,用abstract表示
·抽象类中可以有非抽象方法,但抽象方法必须在抽象类中
注:抽象类不能实例化指的是不能直接实例化,但可以通过多态的方式实例化
接口(interface)
- 格式:
1
public interface 接口名{}
- 特点
- 类和接口不能用继承(extends)而是用实现(implements)
1
public class 类名 implements 接口名{}
- 抽象接口不能实例化,但可以像多态一样用实现类对象实现实例化
- 类和接口不能用继承(extends)而是用实现(implements)
- 接口的实现类
- 要么从小接口中的所有抽象方法,要么是抽象类
- 接口名+Impl一半为接口的实现类
- 接口的成员特点
- 接口中的成员变量默认被final修饰,视为常量,无法修改,有默认修饰符public satic final
- 接口内没有构造方法
- 接口主要是对行为进行抽象
- 接口内不能有非抽象方法
- 类和接口的关系
类和类的关系 | 继承关系,只能单继承,但可以多层继承 |
---|---|
类和接口的关机 | 实现关系,(一个类)可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口 |
接口和接口的关系 | 继承关系,可以单继承,也可以多继承 |
抽象类和接口的区别
- 成员区别:
抽象类:变量、常量;有构造方法、有抽象方法、有非抽象方法
接口:常量;抽象方法 - 关系区别:
类与类:继承,单继承
类与接口:实现,可以单实现,也可以多实现
接口与接口:继承,可以单继承,也可以多继承 - 设计理念区别:
抽象类:对类抽象,包括属性,行为(对事物的抽象)
接口:对行为抽象,主要是行为(对行为的抽象)
- 成员区别:
类名作为形参和返回值
方法的形参是类名,其实需要的是该类的对象
格式:
例如1
2
3本类:public void uesCat(Cat c){//Cat c=new Cat();
c.eat();
}测试类:
1
2Cat c=new Cat();
co.useCat(c);方法的返回值是类名,其实返回的是该类的对象
格式:
例如:1
2
3
4本类:public Cat getCat(){
Cat c=new Cat();
return c;
}测试类:
1
2Cat c2=co.getCat();//new cat();
c2.eat();抽象类是方法的形参与返回值
- 方法的形参是抽象类名,其实需要的是改抽象类的子类对象
- 做形参:运用多态的方法,创建子类,在测试类中用(例如:Animal a=new Cat())表示,然后在方法中调用抽象类(格式参考方法的形参是类名)
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
- 做返回值:运用多态的方法,在本类中用(例如Animal a=new Cat())表示 然后return(格式参考方法的形参是类名)
- 方法的形参是抽象类名,其实需要的是改抽象类的子类对象
接口名作为形参与返回值
- 方法的形参是接口名,其实需要的是该接口的实现类对象
- 做形参:按多态的形式创建实现类(参考抽象类做形参的方式)
- 方法的返回值是接口名,其实返回的是该接口的实现类对象
- 做返回值:按多态的形式创建实现类(参考抽象类做返回值的方法)
- 方法的形参是接口名,其实需要的是该接口的实现类对象
集合
集合基础
- 集合概述:提供一种存储空间可变的存储模型,存储的数据容量可以发生改变
·ArrayList:可以调整大小的数组实现
·:是一种特殊的数据类型,泛型
出现E的地方用引用的数据类型替换即可
例如:1
ArrayList<String>
- ArrayList构造方法和添加方法
方法名 | 说明 |
---|---|
public ArrayList() | 创造一个空的集合对象 |
public boolean add(Ee) | 将制定的元素追加到此集合到末尾 |
public void add(int index,E element) | 在此集合中的指定位置插入指定的 元素(不能跳着添加) |
- ArrayList集合常用方法:
方法名 | 说明 |
---|---|
public boolean remove(Object to) | 删除指定的元素,返回删除是否成功 |
public E remove (int index) | 删除指定索引处的元素,返回被删除的元素 |
public E set(int index,E element) | 修改指定索引处的元素,返回被修改的 元素 |
public E get(int index) | 返回指定索引处的元素 |
public int size() | 返回集合中元素的个数 |
数学中的π用Math.PI表示,Math.PI=3.1314…
集合类体系结构
集合——>Map(双列)
——>Collection(单列)——>List(可重复)
——>Set(不可重复)
Collection(单列集合)
- Collection概述:是单列集合的顶层接口,他表示一组对象,这些对象也称为Collection的元素
- 格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//导包
import java.util.ArrayList;
import java.util.Collection;
public class Collection集合 {
public static void main(String[] args) {
//创建Collection集合的对象
Collection<String> s=new ArrayList<String>();
//添加元素:add(E e)
s.add("Hello");
s.add("word");
s.add("java");
//输出集合对象
System.out.println(s);
}
} - Collection集合的常用方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中删除指定的元素 |
void clear() | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中元素的个数 |
- Collection集合的遍历
Iterator:迭代器,集合的咋您用遍历形式
常用方法:
方法名 | 说明 |
---|---|
E next() | 返回迭代中的下一个元素 |
boolean hasNext() | 如果迭代具有更多元素,则返回true |
List
- List集合概述:有序集合(也称为序列),用户可以精确控制类表中每个元素都插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
与Set集合不同,类表通常润许重复的元素
2. List集合的特点
1. 有序:存储和去除元素的顺序一致
2. 可重复:存储的元素可以重复
3. List集合的特有方法:
方法名 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
Equale() | 做判断,判断集合内是否存在括号内的元素 |
ListIterator(List特有的迭代器)
·允许程序员从任一方向遍历类表的类表迭代器
·常用方法:方法名 说明 E next() 返回迭代中的下一个元素 boolean has Next() 如果迭代具有更多元素,则返回true E previous() 返回列表中的上一个元素 Boolean has Previous() 如果此列表迭代器在相反方向遍历类表是具有更多元素,则返回true 正/反项遍历
1
2
3
4
5
6
7
8
9
10
11
12
13ListIterator<String> lis = l.listIterator();
//正向遍历
while(lis.hasNext()){
String s=lis.next();
System.out.println(s);
}
System.out.println("----------");
//反向遍历
while(lis.hasPrevious()) {
String s = lis.previous();
System.out.println(s);
}
System.out.println("----------");增强for循环
增强for:简化数组和Collection集合的遍历
格式:
For(元素数据类型 变量名:数组或Collection集合){
//在此处使用变量即可,该变量就是元素
}
范例:1
2
3
4int[]arr={1,2,3,4,5};
for(int I;arr){
System.out.println(i);
}数据结构
·数据结构是计算机存储,主旨数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合
·通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率常见数据结构指栈
·数据进入栈模型的过程称为:压/进栈 a-b-c-d
·数据离开栈模型的过程称为:弹/出栈 d-c-b-a
·先进后出,后进先出
·栈是一阵风数据先进后出的模型常见数据结构指队列
·数据从后端进入队列模型的过程称为:入队列 a-b-c-d
·数据从前段离开队列模型的过程称为:出队列a-b-c-d常见数据结构之数组
·查询数据通过索引定位,查询任意数据耗时相同,查询效率高
·删除数据时,要将原始数据删除,同时后边的每个数据前移,删除效率低常见数据结构之链表
·结点(结点的存储位置,存储具体的数据,下一个结点的地址)
·^表示空地址-结束的意思
·链表是一种增删快的模型(对比数组)
·链表是一种查询慢点模型(对比数组)数据结构之二叉树
·只能有一个根结点,每个节点最多支持两个直接子节点
·节点的度:结点拥有的子树的个数,二叉树的度不大于2叶子节点度为0的节点,也被称为终端节点
·高度:叶子结点的高度为1,叶子结点的父结点高度为2,以此类推,根结点的高对最高
·层: 根结点在第一层
·兄弟节点:拥有同一个父结点的两个结点
·二叉查找数:左子树上的所有结点的值都小于根结点的值,右子树上的所有结点的值都大于根结点数据结构之平衡二叉树
·在满足二叉树的大小的规则下,使二叉树尽量矮小
·要求:任意结点的左右两个子树的高度差不超过1,任意结点的左右两个子树都是一棵平衡二叉树
·通过左旋和右旋保持平衡红黑树(平衡二叉B树)
·通过红黑规则平衡
·红黑规则:- 每一个结点或是红色,或是黑色,根结点必须是黑色
- 如果一个结点没有子节点或者父结点,则该结点相应的指针属性值为Nil,这些Nil视为叶结点,叶结点是黑色的
- 如果一个结点是红色的,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)
- 对每一个结点,从该结点到其所有后代叶结点的简单路径上,均高喊形同数目的黑色结点
LinkedList集合(链表)
- 常用方法
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定元素 |
public void addLast(E e) | 将指定元素追加到该列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
泛型
- 概述:可以在编译阶段约束操作的数据类型,比进行检查
·泛型格式<数据类型> 注:泛型智能指出引用数据类型
·集合体系的全部接口和实现都是支持泛型的使用的 - 泛型的好处
- 统一数据类型
- 把运行时起的问题提前到了编译期间,比你那了强类型转换可能出现的异常,因为编译阶段类型就能确定下来
- 泛型类
·定义类的同时定义了泛型的类就是泛型类
·泛型类的格式:修饰符class类名<泛型变量>{}
·范例1
public class MyArray<T>{}
- 泛型方法
·定义方法的同时定义了泛型的方法就是泛型方法
·格式:修饰符<泛型变量>方法返回值 方法名 (形参列表){}
·范例:·作用:方法中可以使用泛型接收一切实际类型的参数,方法更具通用性1
public <T> void show (T t){}
- 泛型接口
·使用泛型定义的接口十九泛型接口
·格式:修饰符 interface 接口名称 <泛型变量>{}
·范例:`作用;泛型接口可以让实现类选择当前功能需要操作的数据类型1
public interface Date<E>{}
- 泛型通配符
·通配符:“?”
·?:可以在“使用泛型”的时候代表一切类型
·E T K V:是在定义泛型时使用的
Set集合
- set集合的特点
- 无序:存取顺序不一致
- 不重复:可以去除重复
- 无索引:没有带索引的方法,所以不能使用普通的for循环遍历,也不能通过索引来获取元素
- set集合实现类特点
- HashSet:无序,不重复,无索引
- LinkedHashSet:有序(存入和读取的先后一样),不重复,无索引
- TreeSet:可排序(基于红黑树进行排序),不重复,无索引
- HashSet底层原理-哈希表
- HashSet集合底层采用哈希表存储数据
- 哈希表是一种对于增删改查数据性能都比较好的结构
- 哈希表的组成
- jdk8以前:底层使用数组+链表
- jkd8开始后:底层采用数组+链表+红黑树组成
- 哈希值:
- 概念:是jdk根据对象的地址,按照某种规则算出来的int类型的数值
- Object类的API:public int hashCode():返回对象的哈希值
- 对象的哈希值特点:
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的
- 哈希值算法
- 创建一个长度为15的数组,数组名table
- 根据元素的哈希值跟数组的长度求余计算出应存入的位置(哈希算法)
- 判断当前位置是否为null,如果是null直接存入
- 如果位置不为null,鞭尸有元素,则调用equals方法比较
- 如果一样,则不存入,如果不一样,则存入数组
- jdk7新元素占老元素位置,指向老元素
- jdk8新元素挂在老元素下面(长度为8,超过8转为红黑树)
- 当数组存满到16*0.75=12时,就自动扩容,每次扩容为原先的2倍
- 如果希望Set集合认为两个内容相同的对象是重复的:
重写对象的hashCode和equals方法 - TreeSet集合默认规则
·对于数值类型:Integer、Double,官方默认按照大小进行生序排序
·对于字符串类型:默认按照首字符的编号进行生序排序
·对于自定义类型如Student对象,TreeSet无法直接排序
·想要使用TreeSte存储子弟你类型,需要制定排序规则
·自定义比较规则- 方法一:让自定义类实现Comparable接口重写里边的compare To方法来定制比较规则
- 第一个大于第二个返回正
- 第一个小于第二个返回负
- 第一个等于等二个返回0,但默认相等删去一个,可用第一个减第二个>=0?1:-1来解决
- 方法二:TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则
- 方法一:让自定义类实现Comparable接口重写里边的compare To方法来定制比较规则
区分
特点 | 对应集合 |
---|---|
元素可以重复,有索引,索引查询快 | ArrayList集合,基于数组 |
元素可以重复,有索引,增删首尾快 | LinkedList集合,基于链表 |
增删改查都快,元素不重复,无序,无索引 | HashSet集合,基于哈希表 |
增删改查都快,元素不重复,有序,无索引 | LinkedHashSet集合,基于哈希表和双链表 |
对对象进行排序 | TreeSet集合,基于红黑树 |
可变参数
- 概述
- 可变参数用在形参中可以接收多个数据
- 可变参数的格式:数据类型…参数名
- 作用:传输参数非常灵活,方便。可以不传输参数,可以传输1个或多个,也可以传输一个数组
- 注意事项
1.一个形参列表中只能有一个可变参数
2.可变参数需要放在其他类表的最后边
注:compareTo()方法:对集合元素进行排序
Collections集合工具类
- 概述:java.untils.Collections:是集合工具类
- 作用:Collection并不属于集合,是用来操作集合的工具类
- 常用API
方法名 说明 public static boolean addAll(Collection<? super T>c,T…elements) 给集合对象批量添加元素 public static void shuffle(List<?> list) 打乱List集合元素的顺序 Sort 按默认顺序排序List集合
Map集合
- Map集合概述和使用
- Map集合是一种双列集合,没换元素班汉两个数据
- Map集合里的每个元素的格式:key=value(链值对元素)
- Map集合也被称为“链值对集合”
- Map集合整体格式
- Collection集合的格式:[元素1,元素2,元素3,…]
- Map集合的完整格式:[key1=value1,key=value2,key3=value2,…]
- Map集合体系特点
- Map集合的特点都是由键决定的
- Map集合的键是无序,不重复的,无索引的,值不做要求(可以重复)
- Map集合后面的重复的键对应的值会覆盖前面重复键的值
- Map集合的键的的值都可以为null
- Map集合实现类的特点
- HashMap:元素按照键是无序的,不重复,无索引,值不做要求。(与Map体系一致)
- LinkedHashMap:元素按照键是有序(按输入顺序输出),不重复,无索引,值不做要求
- TreeMap:元素按照键是排序,不重复,无索引,值无要求
- Map集合的API
Map是双列集合的祖宗接口,他的功能是全部双列集合都可以使用的方法名 说明 V put(L key,V value) 添加元素 V remove(Object key) 根据键删除键值对元素 void clear() 移除所有的键值对元素 boolean containsKey(Object key) 判断集合是否包含指定的键 boolean containsValue(Object valur) 判断集合是否包含指定的值 boolean isEmpty() 判断集合是否为空 int size() 集合的长度,也就是集合中键值对的个数 map1.putAll(map2) 将集合Map2添加到Map1中 - Map集合的遍历方式一:键找值
·先获取Map集合的全部键的Set集合
·遍历键的Set集合,然后通过键提取对应的值方法名 说明 Set keySet() 获取所有键的集合 V get(Object key) 根据键获取值 - Map集合的遍历方式二:键值对
·先把Map集合转换成Set集合,Set集合中每个元素都是键值对实体类型了
·遍历Set集合,让后提取键以及提取值方法名 说明 Set<Map.Entry<K,V>>entrySet() 获取所有键值对对象的集合 K getKey() 获得键 V getValue()) 获取值 - Map集合的遍历方式是三:Lambda
·Jdk8开始的新技术Lambda表达式提供了一种给简单,更直接的遍历集合的方式。方法名 说明 default void forEach(BiConsumer<? super K,? super V>action) 结合lambada遍历Map集合
TreeMap集合的自定义排序
- 自定义排序的规则
1.类实现Comparable接口,重写比较规则
2.集合自定义Comparator比较器对象,重写比较规则
不可变集合
- 概述:
- 不可以被修改的集合
- 集合的数据项在创建时提供,并且在整个生命周期中都不可以改变,否则报错
- 不可变集合的创建方式
·List、set、Map接口中,都存在of方法可以创建不可变集合
方法名 说明 static List of(E…elements) 创建一个具有指定元素的List集合对象 static Set of(E…elements) 创建一个具有指定元素的Set集合对象 static <K,V> Map<K,V> of(E…elements) 创建一个具有指定元素的Map集合对象 - 特点
定义完后不可被修改,或添加,删除
Stream流
概述:简化集合和数组操作的API
Stream流思想
1.先得到集合或数组的Stream流(就是一根传送带)
2.把元素放上去
3.让后就用Stream流简化的PAPI来方便的操作元素Stream流的获取
- 创建一条流水线,并把数据放到流水线上进行操作
- 中间方法:
- 流水线上操作,一次操作完毕后,还可以继续进行其他操作
- 终结方法:
- 一个Stream流只能有一个终结方法,是流水线上的最后一个操作
集合获取Stream流的方法
- 可以使用Collection接口中的默认方法stream()生产流
方法名 说明 default Stream stream() 获取当前集合对象的Stream流 数组获取Stream流的方式
方法名 说明 public static Stream stream(t[] array) 获取当前数组的Stream流 public static Stream of(T… values) 获取当前数组/可变数据的Stream流 Stream流的常用API(中间操作方法)
方法名 说明 Stream filter(Predicate<? super T> predicate) 用于对流中的数据进行过滤 Stream limit(Long maxSize) 获取前几个元素 Stream skip(long n) 跳过前几个元素 Stream,T> distinct() 去除流中重复的元素 static Stream concat(Stream a,Stream b) 合并a和b两个流为一个流 注:
- 中间方法也称为非终结方法,调用完成后返回新的Stream流可以继续使用,支持链式编程
- 在Stream流中无法直接修改集合、数组中的数据
Stream常见的终结方法
方法名 说明 void forEach(Consumer action) 对此流的每个元素执行遍历操作 long count() 返回此流中的元素数 注:中间操作方法,调用完成后就无法继续使用了,原因是不会返回Stream了
收集Stream流
·含义:就是把Stream流操作后 的结果数据传回到集合或数组中去
·Stream流:方便操作集合/数组的手段
·集合/数组:开发中的目的- Stream流的收集方法
方法名 说明 R collect(Collector collector) 开始收集Stream流,指定收集器 - Collectors工具类提供了具体的收集方式
方法名 说明 public static Collector toList() 把元素收集到List集合中 public static Collector toSet() 把元素收集到Set集合中 public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中 注:流只能使用一次
异常
- 异常概述:程序出现了不正常的情况
- 异常体系
- Error:严重问题,不需要处理
- Exception:异常类,他表示程序本身可以处理的问题
- RuntimeException:在编译期是不检查的,无限问题后,需要修改代码
- 非RuntimeException:编译期就必须处理,否则程序不能通过编译,就无法正常运行
- JVM的默认处理方案
- 返回异常的名称,原因,位置输出在控制台
- 程序停止执行
- 异常处理
- 方案一:try…catch…
·格式:·执行流程:1
2
3
4
5try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}- 程序从try里面的代码开始执行
- 出现异常,会自动生成一个异常类对象,该异常继续会被提交给java运行时系统
- 当java运行时系统接收到异常对象时,会到catch中找匹配到异常类,找到后进行异常的处理
- 执行完毕后,程序还可以继续往下执行
- 方案二:Throws:产后护理没有权限,无法处理的异常
·格式:1
throws 异常类名;
- 方案一:try…catch…
- 编译时异常(受检异常)和运行时异常(非受检异常)的区别
- 所有的RuntimeException类及其子类被称为运行时异常,其他的市场都是编译时异常
- 编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译
- 运行时异常:无需显示处理,也可以和编译时异常一样处理
- 自定义异常
格式:范例:1
2
3
4public class 异常类名 extends Exception{
无参构造
带参构造
}1
2
3
4
5
6Public class ScoreException extends Exception{
public ScoreException(){}
public ScoreException(String message){
super(message);
}
} - throws和throw的区别
- throws:
- 用在方法声明后面,跟的是异常类名
- 表示抛出异常,由该方法的电邮着来处理
- 表示出现一种异常的可能性,并不一定会发生这些异常
- throw:
- 用在方法体内,跟的是异常对象名
- 表示抛出异常,由方法体内的语句处理
- 执行throw一定抛出了某种异常
- throws:
日志
- 日志:
- 日志技术的优势:
- 可以将系统执行的信息选择性的记录到指定位置(控制台、文件中、数据库)
- 可以随时以开关的形式控制是否记录日志,无序修改源代码
- 日志技术体系
日志规范接口:一些接口,提供给日志的实现框架设计的标准
Commons Logging——JCL
Simple Logging Facade for Java——slf4j
日志实现框架:牛人或第三方公司已经做好的日志记录实现代码,可以直接拿去使用
·Log4j
·JUL(java.util.longgiing)
·Logback
- 日志技术的优势:
- Logback日志框架
- 官方网站
- 基于slf4j的日志规范实现的框架
- 技术模块
·Logback-core:为其他两个模块奠定基础,必须有
·Logback-classic:他是log4j的一个改良版本,同时它完整的实现了slf4JAPI
·Logback-access模块与Tomcat和Jetty等Servelt容器集成。以通过HTTP访问日志功能 - 必用模块
·slf4j-api:日志规范
·logback-core:基础模块
·logback-classic:他是log4j的一个改良版本,同时它完整的实现了slf4JAPI - 在代码中获取日志对象输出到控制台的配置标志:
1
public static final Logger LOGGER=LoggerFactory.gerLoger(“类对象”);
输出到系统文件的配置标志:1
<appender name = "CONSOLE" class = "ch.qos.logback.core.ConsoleAppender>
1
<appender name = “FILE” class= “ch.qos.logback.core.rolling.RollingFileAppender”>
- 实现
1.在项目新建文件夹lib,导入Logback相关jar包(logback-classic、logback-core、slf4j-api),并添加到项目依赖库- 在Logback核心配置文件logback.xml拷贝到src目录下
- 在代码中获取日志对象(public static final Logger LOGGER=loggerFactory.getLogger())
- 日志级别
TRACE < DEBUG < INFO < WARN < ERROR(默认基本为debug) - 案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//快速搭建Lpgback日志框架,记录程序运行情况并存入控制台,文件中
public class Logbock11 {
//创建Logback的日志对象,代表了日志技术
public static final Logger logger=LoggerFactory.getLogger("Logback11");
public static void main(String[] args) {
try {
logger.debug("记录我的main方法");
logger.info("开始记录");
int a=10;
int b=20;
logger.trace("a="+a);
logger.trace("b="+b);
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace();
logger.error("功能出现异常"+e);
}
}
}
File类
概述:File可以定位文件,惊喜删除,获取文件本身,但不能读写文件内容
File类的创建对象
方法名 说明 public File(String pathname) 根据文件路径创建文件对象 public File(String parent,String child) 从父路径名字字符串和子路径名字字符串创建文件对象 public File(File parent,String child) 根据父路径对应的文件和对象和子路径名字字符串创建文件对象 ·绝对路径: 电脑硬盘所对路径
·相对历经:相对于工程来说,工程名/src/具体路径
不能拿文件夹的大小,读取的话是文件夹本身的大小,不包括里边东西的大小File类文件的判断文件类型,货物文件信息功能
方法名 说明 public boolean isDirectory() 测试此抽象路径名表示的File是否为空文件夹 public boolean isFile() 测试此抽象路径名表示的File是否为文件夹 public boolean exists() 测试此抽象路径名表示的File是否存在 public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串 public String getPath() 将此抽象路径名转换为路径名字符串 public String getName() 返回由此路径名表示的文件或文件夹的名称 public long lastModified() 返回文件最后修改时间的毫秒值 File类的遍历功能
方法名 说明 public String[] list() 获取当前目录下的“以及文件名称”到一个字符串数组中去返回 public File[] listFiles()(常用) 获取当前目录下所有的“一级文件对象”到一个文件对象数组中去返回 - listFiles方法注意事项
- 当调用者不存在时,返回null
- 当调用者是一个文件时,返回null
- 当调用者是一个空文件夹时,返回一个长度为0的数组
- 当调用者是一个有内容的文件夹是,将里面所有文件和文件夹的路径放在File数组中返回
- 当调用者是一个有隐藏文件的文件夹时,将里面所有文件和文件夹路径放在File数组中返回,包含隐藏内容
- 当调用者是一个需要权限才能进入的文件夹是,返回null
- listFiles方法注意事项
File类创建文件的功能
方法名 说明 public boolean createNewFile() 创建一个新的空的文件 public boolean mkdir() 只能创建一级文件夹 public boolean mkdirs() 可以创建多集文件夹 File类删除文件的功能
方法名 说明 public boolean delete() 删除由此抽象路径名表示的文件或空文件夹 注:
·delete方法是直接删除不走回收站,如果删除的是一个文件且文件没有被占用则直接删除
·delete方法默认只能删除空文件夹
字符集
概述:计算机底层不能存储字符,只能存储二进制
结论:计算机底层可以表示十进制编号,计算机可以给人类字符进行编号存储,这套编号规则就是字符集
·ASCII:使用1个字节存储一个字符,一个字节是8位,共可以表示128个字符信息
·GBK:window系统默认的编码,兼容ASCII码表,也包含几万个汉字,并支持繁体汉字依旧部分日韩文字
注:GBK是中国的编码一个中文以两个字节的形式存储。
·Unicode码表:是计算机里的一项业界字符编码标准,容纳了时间大多数国家的场景文字和字符
注:中文一般以3个字节形式存储
兼容ASCII编码表
技术人员都应该使用UTF-8的字符编码集合
编码前和编码后的字符需要一致,否则会出现中文乱码编码和解码
- Sting编码
方法名 说明 byte[]getBytes() 使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中 byte[]getBytes(String charesetName) 使用指定的字符集将String编码为一系列字节,将结果存存储到新的字节数组中 - String解码
方法名 说明 String(byte[] bytes) 通过使用平台的默认字符集解码指定的字节数组来构造新的String String(byte[]bytes,String charsetName) 通过制定的字符集解码制定的字节数组来构造新的String
- Sting编码
IO流
IO流(输入、输出流)读写数据
I:input:数据从硬盘文件读入内存的过程
O:output,是内存程序将数据从内存写到硬盘文件的过程
按流的数据最小单位分为
字节流(音乐)-操作所有类型文件
字符流(文档)-操作纯文本文件
类型(抽象类) | 说明 |
---|---|
字节输入流(InputStream) | 以内存位基准,将磁盘文件/网络数据以字节的形式读入到内存中 |
字节输出流(OutputStream) | 以内存位基准,将内存中的数据以字节写出到磁盘文件或网络数据中 |
字符输入流 (Reader) | 以内存位基准,将磁盘文件/网络数据以字符的形式读入到内存中 |
字符输出流(Writer) | 以内存位基准,将内存中的数据以字符写出到磁盘文件或网络数据中 |
·flush()刷新流,还可继续写数据
·close()关闭流,释放资源
实现类:File+抽象类
字节流
字节输入
- 作用:以内存为基准,把磁盘文件中的数据以字节形式读取到内存中
- 方法:
方法名 说明 FileInputStream(File file) 创建字节输入流管道与源文件对象接通 FileInputStream(String pathname) 创建字节输入流管道与源文件路径接通 read() 每次读取一个字节返回,没有字节可读返回-1 read(byte[] buffer) 每次读取一个字节数组返回,没有字节可读返回-1 - 实例:
1
2
3
4File f = new File("Delete/src/data.txt");
InputStream is = new FileInputStream(f);//或者直接将f换成路径
byte[] buffer = new byte[(int)f.length()];
System.out.println(new String(buffer));
字节输出
- 作用:以内存为基准,把内存中的数据以字节形式写出到磁盘文件中去的流
- 方法:
方法名 说明 FileOutputStream(File file,Boolean append) 创建字节输出流管道与源文件对象接通,可追加s数据 FileOutputStream(String filepath) 创建字节输出流管道与源文件路径接通 write() 写一个字节出去 write(byte[] buffer,int pos,int len) 写一个字节数组的一部分出去
字符流
字符流输入
- 作用:以内存为基准,把磁盘文件中的数据以字符形式读取到内存中
- 方法:
方法名 说明 FileReader(File file) 创建字符输入流管道与源文件对象接通 FileReader(String pathname) 创建字符输入流通道与源文件路径接通 read() 每次读取一个字符返回,没有字符可读返回-1‘ read(char[] buffer) 每次读取一个字符数组,返回读取字符个数,无字符可读返回-1 - 实例:
1
2
3
4
5
6
7Reader fr = FileReader("Delete/src/data.txt");
char[] buffer = new char[1024];
int len;
while((len = fr.read(buffer)) != -1){
String rs = new String(buffer, 0 ,len);
System.out.print(rs);
}
字符流输出
- 作用:以内存为基准,把内存中的数据以字符形式写到磁盘文件中的流
- 方法:
方法名 说明 FileWriter(File file,boolean append) 创建字符输出流管道与源文件对象接通,可追加数据 FileWriter(String filepath) 创建字符输出流管道与源文件路径接通
缓冲流:
- 作用:缓冲流自带缓冲区,可以提高原始字节流、字符流读写数据的性能
- 类:Buffered+
如:BufferedInputStream字节缓冲流
- 字节缓冲输入流:BufferedInputStream,提高字节输入流读取数据的性能,读写功能上并无变化
- 字节缓冲输出流:BufferedOutputStream,提高字节输出流读取数据的性能,读写功能上并无变化
- 构造器
构造器 | 说明 |
---|---|
public BufferedInputStream(InputStream is) | 可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提要字节输入流读数据的性能 |
public BufferdeOutputStream(OutputStream os) | 可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能 |
字符缓冲流
- 字符缓冲输入流:BufferedReader
- 作用:提高字符输入流读取数据的性能,除此之外多了按行读取数据的功能
- 构造器&方法
构造器 说明 public BufferedReader(Reader r) 可以把低级的字符输入流包装成一个高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能 方法名 说明 public String readLine() 读取一行数据返回,如果没有读取完毕,无行可读返回null - 字符缓冲输出流:BUfferedWriter
- 作用:提高字符输出流写取数据的性能,除此之外多了换行功能
- 构造器&方法
构造器 说明 public BufferedWriter(Writer w) 可以把低级的字符输出流包装成一个高级的缓冲字符输出管道,从而提高字符输出流写数据的性能 方法名 说明 public void newLine() 换行操作
转换流(如将UTF-8转为GBK)
- 字符输入转换流InputStreamReader:将原始字节流按照指定编码专程字符输入流
- 构造器
构造器 | 说明 |
---|---|
public InputStreamReader(InputStream is) | 可以把原始的字节输入流按照代码默认编码转换成字符输入流(几乎不用) |
public InputStreamReader(InputStream is,String charset) | 可以把原始的字节输入流按照代码指定编码转换成字符输入流,这样字符流中的字符就不会乱码 |
- 字符输出转换流OutpputStreamWrite:可以吧字节输出流按照指定编码转换成字符输出流
- 方式一:在“准备输出的字符”.getBytes(要转换的编码)
- 构造器
构造器 | 说明 |
---|---|
public OutpputStreamWrite(OutputStream os) | 可以把原始的字节输出流按照代码默认编码转换成字符输出流(几乎不用) |
public OutpputStreamWrite(OutputStream os,String charset) | 可以把原始的字节输出流按照代码指定编码转换成字符输出流,这样字符流中的字符就不会乱码 |
- 对象序列化ObjectOutputStream
- 作用:以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列话
- 对象反序列化ObjectInputStream
- 作用:以内存为基准,把存储到磁盘文件中去的对象数据恢复成内存中的对象,称为对象饭序列化
注:如果不想参加序列化,在定义类型前家transient
如:pirvate transient String a;
可以申请序列话的版本号
格式这能是这样:
private static final long serialVersionUID = 1;
序列化的版本号和反序列号的版本号需要一样才不会出错
打印流:
- 概述:打印流可以实现方便、高效的打印数据到文件中,打印什么就是什么数据
- 分为两个类:
- 字节流:PrintStream
- 字符流:PrintWriter
- PrintStream构造器&方法
构造器 | 说明 |
---|---|
public PrintStream(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintStream(File f) | 打印流直接通向文件对象 |
public PrintStream(String filepath) | 打印流直接通向文件路径 |
方法名 | 说明 |
public void print(Xxx xx) | 打印任意类型的数据出去 |
- PrintWriter构造器&方法
构造器 | 说明 |
---|---|
public PrintWriter(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintWriter(Writer w) | 打印流直接通向字符输出流管道 |
public PrintWriter(File f) | 打印流直接通向文件对象 |
public PrintWriter(String filepath) | 打印流直接通向文件路径 |
方法名 | 说明 |
public void print(Xxx xx) | 打印任意类型的数据出去 |
- PrintStream和PrintWriter的区别
·打印数据功能上是一摸一样的,收拾使用方便,性能高效
·PrintStream继承自字节输出流OutputStream,支持写字节数据的方法
·PrintWriter继承自字符输出流Writer,支持写字符数据出去 - 输出语句重定向
·可以吧输出语句打印位置改到文件
格式:1
2PrintStrean pr = new PrintStream(“文件位置“);
System.setOut(pr);
多线程
- 概述:多条执行流程
多线程的创建
方式一:继承Thread类
- 实现方法:
- 定义一个子类MyThread继承线线程类java.lang.Thread,重写run()方法
- 创建MyThread类的对象
- 调用线程对象的start()方法启动线程(启动后还是执行的run方法)
- 优缺点:
- 优点:编码简单
- 缺点:线程类已经继承Thread,无法继承其他类,不利于扩展
- Thread的构造器
构造器 说明 public Thread(String name) 可以为当前线程制定名称 public Thread(Runnable target) 封装Runnable对象成为线程对象 public Thread(Runnable target,String name) 封装Runnable对象成为线程对象,并制定线程名称 - Thread的常用方法
方法名 说明 String getName() 获取当前线程的名称,默认线程名称是Thread-索引 void setName() 设置线程名称 public static Thread currentThread() 返回对当前正在执行的线程对象的引用 public void run() 线程任务方法 public void start() 线程指定方法 public static void sleep(long time() 让当前线程休眠指定时间后在继续执行,单位为毫秒 - 实现方法:
方式二:实现Runnable接口
- 实现方法:
- 定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法
- 创建MyRunnable人物对象
- 把MyRunnable任务对象交给Thread处理
- 调用线程对象start()方法启动线程
- 优缺点:
- 优点:线程任务类只是实现接口,可以继续继承和实现接口,扩展性强
- 缺点:编程多一层对象包装,如果线程又执行结构是不可以直接返回的。
- 实现方法:
方式三:实现Callable接口(JDK5.0新增)
- 实现方法:
- 得到任务对象
- 定义类事项Callable接口,重写call方法,封装要做的事情
- 用FutureTask把Callable对象封装成任务对象
- 把线程任务对象交给Thread处理
- 调用Thread的start()方法启动线程,执行任务
- 线程执行完毕后,通过FutureTask的get方法获取任务执行的结果
- 得到任务对象
- 优缺点:
- 优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强,可以在线程执行完毕后获取线程的执行的结果
- 缺点:编码复杂
- FutureTask的API
方法名 说明 public FutureTask<>(Callable call) 把Callable对象封装成FutureTask对象 public V get()throws Exception 获取线程执行call方法返回的结果 - 实现方法:
三种方式的对比
方式 | 优点 | 缺点 |
---|---|---|
继承THread类 | 编程比较简单可以直接使用Thread类中的方法 | 扩展性较差,不能再继承其他类,不能返回线程执行的结果 |
实现Runnable接口 | 扩展性强,实现该接口的同时还可以继承其他类 | 编程相对复杂,不能返回线程执行结果 |
实现Callable接口 | 扩展性强,实现该类接口的同时还可以继承其他的类,可以得到线程执行的结果 | 编程相对复杂 |
线程安全
概述:
- 个多线程同时操控一个共享资源的时候可能会出现业务安全问题,称为线程安全问题
- 线程同步->解决线程安全问题
- 核心思想:
加锁:把贡献资源进行上锁,每次只能一个线程进入访问完毕后解锁,然后其他线程才能进来
锁是可以跨方法的
方式一:同步代码块
- 作用:把线程安全问题的核心代码给上锁
- 原理:每次只能一个线程进入,执行完毕后自动解锁,其他线程才可以进来执行
- 格式:
1
2
3synchronized(同步锁对象){
操作共享资源的代码(核心代码)
} - 锁对象要求
- 理论上:锁对象只要对于当前同时执行的线程来说是同一个对象即可
- 锁对象的规范要求
- 规范上:建议使用贡献资源作为锁对象
- 对于实例方法建议使用this作为锁对象
- 对于静态方法建议使用字节码(类名.class)对象作为锁对象
- 格式
1
2
3
4
5public static void run(){
synchronized(Shiyan.class){
}
}
方式二:同步方法
- 作用:把出现线程安全问题的核心方法给上锁
- 原理:每次只能一个线程进入,执行完毕后自动解锁,其他线程才可以进来执行
- 格式:
1
2
3修饰符 synchronized 返回值类型 方法名称(形参列表){
提供共享资源的代码
} - 同步方法底层原理
- 同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码
- 如果方法是实例方法:同步方法默认用this作为锁对象,但是代码要高度面向对象
- 如果方法是静态方法:同步方法默认用类名.class作为锁对象
- 大型并发系统环境中使用Executors如果不注意可能会出现系统风险
方法名称 存在问题 public static ExecutorService newFixedThreadPool(int nThreads) 允许请求的任务队列长度是Integer.MAX_VALUE,可能出现OOM错误(java.lang.OutOfMemoryError) public static ExecutorService newSingleThreadExecutor() 允许请求的任务队列长度是Integer.MAX_VALUE,可能出现OOM错误(java.lang.OutOfMemoryError) public static ExecutorService newCachedThreadPool() 创建的线程数量最大上限是Integer.MAX_VALUE,线程数可能会随着任务1:1增长,也可能出现OOM错误(java.lang.OutOfMemoryError) public static ScheduledExecutorService newScheduledExecutorService(int corePoolSize) 创建的线程数量最大上限是Integer.MAX_VALUE,线程数可能会随着任务1:1增长,也可能出现OOM错误(java.lang.OutOfMemoryError) 方式三:Lock锁
- 为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock
- Lock实现提供比例使用synchronized方法和语句可以获取更广泛的锁定操作
- Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来构建Lock锁对象
方法名 说名 public ReentrantLock() 获得lock锁的实现类对象 - Lock的API
方法名 说明 void lock() 获得锁 void unlock() 释放锁 - 最好用finall调用lock.unlock()方法,防止中途出现bug导致无法解锁以后无法访问
线程通信
- 概述:
- 线程通讯就是线程间相互发送数据,线程通讯通常共享一个数据的方式实现
- 线程间会根据共享数据的情况决定自己该怎么做,以及通知其他线程该怎么做
- 常见的线程通讯模型
- 生产者鱼消费者模型:生产者负责生出数据,消费者负责消费数据
- 要求:生产者线程生产完数据后,唤醒消费者,然后等待自己;消费者消费完数据后,唤醒生产者,然后等待自己
- 注:
1. sleep状态不需要强锁,一但醒来直接运行
2. wait:时间到了或被唤醒并抢到锁才能运行
- 等待和唤醒方法
方法名 | 说明 |
---|---|
void wait() | 让当前线程等待并释放所占锁,直到另一个线程调用notify()方法或notifyAll()方法 |
void notify() | 唤醒正在等待的单个线程 |
void notifyAll() | 唤醒正在等待的所有线程 |
线程池
概述:线程池,接口:ExecutorService:可以复用线程的技术
如果不使用线程池的话用户每发起一个请求,就要创建一个新线程,会严重影响系统的性能获取线程池对象
方式一:实现类ThreadPoolExecutor自创建一个线程池对象
- ThreadPoolExecutor构造器的参数说明·参数一:指定线程池的线程数量(核心线程):corePoolSize—–>不能小于0
1
2
3
4
5public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,
long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
·参数二:指定线程池可支持的最大线程数:maximumPoolSize—–>最大数量>=核心线程数量
·参数三:指定临时线程的最大存活时间:keepAliveTime—–>不能小于0
·参数四:注定存活时间的单位(秒、分、时、天):unit—–>时间单位
·参数五:指定任务队列:wprkQueue—–>不能为null
·参数六:指定用哪个线程工厂创建线程:threadFactory—–>不能为null
·参数七:指定线程忙,任务满的时候,新任务来了怎么办:handler—–>不能为null - ExecutorService的常用方法
方法名 说明 void execute(Runnable command) 执行任务/命令,没有返回值,一般用来执行Runnable任务 Future submit(Callable task) 执行任务,返回未来任务对象获取线程结果,一般来执行Callable任务 void shutdown() 等任务执行文笔后关闭线程池 List shutdownNow() 立即关闭,停止正在执行的任务,并返回队列中未执行的任务 - 新任务拒绝策略
策略 详解 ThreadPoolExecutor.AbortPolicy 丢弃任务并抛出RejectedExecutionException异常(这是默认策略) ThreadPoolExecutor.DiscardPolicy 丢弃任务,但是不抛出异常(不推荐) ThreadPoolExecutor.DiscardOldestPolicy 抛弃队列中等待最久的任务,然后把当前任务加入队列中 ThreadPoolExecutor.CallerRunsPolicy 由主线程负责调用任务的run()方法从而要过线程池直接执行 - ThreadPoolExecutor构造器的参数说明
方式二:Executors(线程池工具类)得到线程池对象
- Executors:线程池的工具类通过调用方法返回不同类型的线程池对象
方法名 说明 public static ExecutorService newCachedThreadPool() 线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了一段时间则会被回收 public static ExecutorService newFixedThreadPool(int nThreads) 创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个信线程代替他 public static ExecutorService newSingleThreadExecutor() 创建只有一个线程的线程池对象,如果该线程出现了异常而结束,那么线程池会补充一个新线程 public static ScheduledExecutorService newScheduledExecutorService(int corePoolSize) 创建一个线程池,可以实现在给定的延迟后运行任务或者定期执行任务 - 注:Executors的底层多集其实也是基于想成池的实现类ThreadPoolExecutor创建线程池对象的
- 大型并发系统环境中使用Executors如果不注意可能会出现系统风险,详情请看多线程/线程安全
在大型互联网场景的线程池使用建议使用ThreadPoolExecutor来制定线程池参数,这样可以明确线程池的运行规则,避免资源耗尽的风险
线程的六种状态
线程状态 | 描述 |
---|---|
NEW(新建) | 线程刚被创建,但是并未启动 |
Runnable(可运行) | 线程已经调用了start()等待CPU调度 |
Blocked(锁阻塞) | 线程在执行的时候未竞争到锁对象,则该线程进入Blocked状态 |
Waiting(无限等待) | 一个线程进入Waiting状态,另一个线程调用notify或者notifiAll方法才能唤醒 |
TimedWaiting(计时等待) | 同waiting状态,有几个方法超市参数,调用它们将进入TimedWaiting状态,带有超时参数的常用方法有Thread.sleep、Object.wait |
Teminated(被终止) | 因为run方法正常退出而死亡或因为没有捕获的异常终止了run方法而死亡 |
并发,并行
·正在运行的程序(软件)就是一个独立的进程,线程是数亿进程的,多个线程就是并发与并行同时进行的
·并发的理解:cpu分时轮询的执行线程
·cpu同时处理线程的数量是有限的
·cpu会轮询为系统的每个线程服务,由于cpu切换的速度很快,给我们的感觉这些线程在同时执行,这就是并发
·并行的理解:同一时刻同时在执行
·在同一时刻是那个,同时有多个线程在被cpu处理并执行
线程的生命周期
线程的状态:也就是线程从生到死的过程,以及中间经历的各种状态及状态转换
网络编程
基础
- 概述:可以让程序与网络上的其他设备中的程序进行数据交互
- 常见的通信模式有如下两种形式
- Client-Server(CS)
- 客户端(Client):
·需要程序员开发
·用户需要安装客户端 - 服务端(Server):
·需要程序员开发
- 客户端(Client):
- Browser-Server(BS)
- 客户端(Browser):
·不需要程序员开发实现
·用户需要安装浏览器 - 服务端(Server):
需要程序员开发实现
- 客户端(Browser):
- Client-Server(CS)
- 通讯三要素:
- IP地址:设备在网络中的地址,是唯一的标识
- 端口:应用程序在设备中的唯一标识
- 协议:数据在网络传输的规则,常见的协议有UDP协议和TCP协议
IP地址
- IP(InternetProtocol):全称“互联网协议地址”,是分配给上网设备的唯一标志
- 常见的IP分类为:IPv4和IPv6
- IPv4:32位(4字节),点分十进制表示法
- IPv6:128位(16字节),冒号十六进制表示法,IPv6分成8个整数,每个整数采用四个十六进制位表示,数之间用冒号(:)分开
- IP地址
- 公网地址、和私有地址(局域网使用)
- 168.开头的就是常见的局域网地址,范围即为192.168.0.0—192.168.255.255
- IP常用指令
·ipconfig:查看本机ip地址
·ping IP地址:检查网络是否看见通
·ping 域名:检查电脑是否联网 - 特殊IP地址
·本机IP:127.0.0.1或者localhost:成为回送地址也可称本地回环地址,只会寻找当前所在的本机
·需要ping 127.0.0.1或ping localhost
- IP地址操作类-InetAddress
·此类表示Internet协议(IP)地址
方法名 | 说明 |
---|---|
public static InetAddress getLocalHost() | 返回本机的地址对象 |
public static InetAddress getByName(String host) | 得到指定主机的Ip地址对象,参数是域名或者IP地址 |
public String getHostName() | 获取此IP地址的主机名 |
public String getHostAddress() | 返回IP地址字符串 |
public boolean isReachable(int timeout) | 在指定毫秒内联通IP地址对应的主机,连通返回true |
端口号:
- 端口号:标识正在计算机设备上运行的进程(程序),被规定为一个16位的二进制,范围是0~65535
- 端口类型
- 周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)
- 注册端口:1024~49151,分配给用户进程或某些应用程序(如:Tomcat占用8080,MySQL占用3306)
- 动态端口49152到65535,之所以称为动态端口,是因为它一般不固定分配某种进程,而是动态分配。
协议:
协议:连接和通信数据的规则被称之为网络通信协议
网络通讯协议有两套参考模型
- OSI参考模型:世界互联协议标准,全球通讯规范,由于此模型过于理想化,未能在因特网上广泛推广
- TCP/IP参考模型(或TCP/IP协议):事实上的国际标准
传输层的两个常见协议
- TCP:传输控制协议
- UDP:用户数据协议
UDP通信
- DatagramPacket:数据包对象
构造器 说明 public DatagramPacket(byte[] buf,int length,InetAddress address,int port) 创建发送端的数据包对象,buf:要发送的内容,字节数组、length:要发送内容的字节长度、address:接收端的IP地址对象、port:接收端的端口号 public DatagramPacket(byte[] buf,int length) 创建接收端的数据包对象 buf:用来存储接收的内容、length:用来接收内容的长度 - DatagramPacket常用方法
方法名 说明 public int getLength() 实际接收到的字节数 - DatagramSocket:发送端和接收端对象
构造器 说明 public DategramSocket() 创建发送端的Socket对象,系统会随机分配一个端口号 public DategramSocket(int port) 创建接收端的Socket对象并指导端口号 - DategramSocket类成员方法
方法名 说明 public void send(DatagramPacket dp) 发送数据包 public void receive(DatagramPacket p) 接收数据包 - UDP通信的三种方式
- 单播:单体主机与单台主机之间的通信
- 广播:当前主机与所在网络中的所有主机通信
- 使用广播地址255.255.255.255
- 发送端发送的数据包的目的地写的是广播质地、且指定端口。(255.255.255.255,9999|
- 本机所在网段的其他主机的程序只要匹配端口成功就可以收到消息的(9999)
- 组播:当前主机与选定的一组主机的通信
- 使用组播地址:224.0.0.0~239.255.255.255
- 发送端的数据包的目的地是组播IP
- 接收端必须绑定该组播IP,端口好友对应发送端的目的端口,这样即可收到该组播消息
- DategramSocket的子类MulticastSocket可以在接收端绑定组播IP
TCP通信
在java中只要是使用java.net.Socket类实现通讯,底层即是使用了TCP协议
客户端:
- Socket
构造器 说明 public Socket(String host,int port) 创建发送端的Socket对象与服务端连接,参数为服务端程序的IP和端口 - Socket类成员方法
方法名 说明 OutputStream getOutputStream() 获得字节输出流对象 InputStream getInputStream() 获得字节输入流对象 3.TCP通讯,使用线程池优化,适合客户端通信时常较短的场景,服务端可以复用线程处理多个客户端,可以避免系统瘫痪
BS开发
单元测试、反射、注解、动态代理
单元测试
概述:单元测试就是针对最小功能单元编写代码测试,java程序最小的功能单元是方法,因此,单元测试就是针对java方法的测试,进而检查方法的正确幸
Junit单元测试框架
- 优点:
- 可以灵活的选择执行那些测试方法,可以一键执行全部测试方法
- 可以灵活生成全部方法的测试报告
- 单元测试中的某个方法测试失败,不会影响其他方法的测试
- 优点:
测试方法注意点:
- 必须是公开的,无参数,无返回值的方法
- 测试方法必须使用@Test注解标记
Junit4常用注解
注解 说明 @Test 测试方法 @Begor 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次 @After 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次 @BeforClass 用来静态修饰方法,该方法会在所有测试方法之前执行一次 @AfterClass 用来静态修饰方法,该方法会在所有测试方法之后执行一次 ·开始执行的方法:初始化资源
·执行完之后的方法:释放资源Junit5常用注解
注解 说明 @Test 测试方法 @BegorEach 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次 @AfterEach 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次 @BeforClassAll 用来静态修饰方法,该方法会在所有测试方法之前执行一次 @AfterClassAll 用来静态修饰方法,该方法会在所有测试方法之后执行一次 ·开始执行的方法:初始化资源
·执行完之后的方法:释放资源
反射
概述:反射是指对于任何一个class类,在“运行的时候”都可以直接的恶道这个类的全部成分
·在运行时,可以直接得到这个类的构造器对象:Constructor
·在运行时,可以直接得到这个类的成员变量对象:Field
·在运行时,可以直接得到这个类的成员方法对象:Method
·这种运行时获取类信息以及动态调用类中成分的能力称为java语言的反射机制反射的关键:反射的第一步都是先得到编译后的class类对象,然后就可以得到class的全部成分
获取Class对象
- 格式一:
1
Class c1 = Class.forName("包名+对象");
- 格式二:
1
Class c2 = 类名.class;
- 格式三:
1
2
3例如:
Student s = new Student();
Class c3 = s.getClass();
- 格式一:
获取构造器
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
Class类中用于获取构造器的方法
方法名 说明 Constructor<?>[] getConstructors() 返回搜有构造器对象的数组(只能拿public的) Constructor<?>[] getDeclaredConstructors() 返回所有构造器对象的数组,存在就能拿到 Constructor getConstructor(Class<?>…parameterTypes) 返回单个构造器对象(只能拿public的) Constructor> getDeclaredConstructor(Class>…parameterTypes) 返回单个构造器对象,存在就能拿到 使用反射技术获取构造器对象并使用
·获取构造器的作用依然是初始化一个对象返回
·Constructor类中用于创建对象的方法符号 说明 T newInstance(Object… initargs) 根据指定的构造器创建对象 public void setAccessible(boolean flag) 设置为true,表示取消访问检查,进行暴力反射
注:遇到私有构造器,可以暴力反射”.setAccessible(true):”
获取成员变量对象
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
Class类中用于获取成员方法的方法
方法名 说明 Field[] getFields() 返回所有成员变量对象的数组(只能拿public的) Field[] getDeclaredFields() 返回所有成员变量对象的数组,存在就能拿到 Field getField(String name) 返回单个成员变量对象(这能拿public的) Field getDeclaredField(String name) 返回单个成员变量对象,存在就能拿到 使用反射技术获取成员变量对象并使用
·获取成员变量的作用依然是在摸个对象中取值,赋值
·Field类中用于取值、赋值的方法符号 说明 void set(Object obj,Object value) 赋值 Object get(Object ob) 获取值
注:遇到私有成员变量,可以暴力反射”.setAccessible(true):”
获取方法对象
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
Class类中用于获取成员方法的方法
方法名 说明 Method[] getMethods() 返回所有成员方法对象的数组(只能拿public的) Method[] getDeclaredMethods() 返回所有成员方法对象的数组,存在就能拿到 Method getMethod(String name,Class<?>…parameterTypes) 返回单个成员方法对象(这能拿public的) Methed getDeclaredMethod(String name,Class<?>…parameterTypes) 返回单个成员方法对象,存在就能拿到 使用反射技术获取方法对象并使用
·获取成员方法的作用依染是在某个对象中进行执行此方法
·Method类中用于出发执行的方法符号 说明 Object invoke(Object obj,Object…args) 运行方法,参数一:用obj对象调用该方法、参数二:调用方法的传递参数(如果没有不写)、返回值:方法的返回值(如果没有就不写
注:遇到私有方法,可以暴力反射”.setAccessible(true):”
反射的作用
·绕过变异阶段为集合添加数据
·可以在运行时得到一个类的全部成分然后操作
·可以破话封装行(很突出)
·可以破话泛型的约束性(很突出)
·更重要的用途是适合做java高级框架
注解
概述:
- java注解(Annotation)又称java标注,是jdk5.0引入的一种注释机制
- java语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注
作用:对java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定
自定义注解
- 自定义注解就是自己做一个注解来使用
- 格式
1
2
3public @interface 注解名称{
public 数学类型 属性名() default 默认值;
} - 特殊属性
- value属性:如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
- 但有多个属性,且多个属性没有默认值,那么value名称是不能省略的
元注解:注解注解的注解
- 常见的:
- @Target:原始自定义指数只能在哪些地方使用
- @Retention:申明注解的生命周期
- @Target中可使用的值定义在ElementType枚举类中,常用值如下:
·TYPE:类,接口
·FIELD:成员变量
·METHOD:成员方法
·PARAMETER:方法参数
·CONSTRUCTOR:构造器
·LOCAL_VARIABLE:局部变量 - @Retention中可使用的值定义在RetentionPolicy枚举类中,常用值如下:
·SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
·CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
·RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)
- 常见的:
注解解析:
概述:注解的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容
与注解解析相关的接口
- Annotation:注解的顶级接口,注解都是Annotation类型的对象
- AnnotatedElement:该接口定义了与注解解析相关的解析方法
方法名 说明 Annotation[] getAeclaredAnnotations() 获得当前对象上使用的所有注解,返回注解数组 T getDeclareAnnotation(Class annotationClass) 根基注解类型获得对应的注解对象 boolean isAnnotationPresent(Class annotationClass 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false
所有的类成分Class、Method、Filed、Constructor、都实现了AnnotatedElement接口,它们都拥有解析注释的能力
解析注解的技巧
·注解在哪个成分上,我们就先拿哪个成分对象
·比如注解作用在成员方法上,则要先获得该成员方法对应的Method对象,再来拿上面的注解
·比如注解作用在类上,则要该类的Class对象,再来拿上面的注解
·步入注解作用在成员变量上,则要获得该成员变量对应的Field对象,再来拿上面的注解
动态代理
- 概述:代理:某些场景下对象会找一个代理对象,来辅助自己完成一些工作,代理主要是对对象的行为额外做一些辅助操作
- java中代理的代表类是:java.lang.reflect.Proxy
- Proxy提供了一个静态方法,用于为对象生产一个代理对象返回·参数一:定义代理类加载器
1
public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h)为对象返回一个代理对象
·参数二:代理类实现的接口列表
·参数三:将方法调用分派到处理程序。(代理对象的核心处理程序) - 动态代理的优点
- 可以在不改变方法源码的情况下,实现对方法功能的增强,提高了代码的复用
- 简化了编程工作、提高了开发效率,同时提高了软件系统的可扩展性
- 可以被代理对象的所有方法做处理
- 非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接口本身做代理
XML
XML基础
- 概述:XML是可扩展标记语言,他是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据
- 特点和使用场景
- 一是纯文本,默认使用UTF-8编码,二是可嵌套
- 如果把XML内容存为文件,那么它就是一个XML文件
- XML的使用场景:XML内容经常被当作成消息进行网络传输,或作为配置文件用于存储系统的信息
- XML的创建:就是创建一个XML类型的文件,要求文件的后缀必须使用xml,例如hello_world.xml
- XML语法规则
·XML文件的后缀名为:xml
·文档声明必须是第一行version:XML默认的版本号吗,该属性是必须存在的1
<?xml version="1.0" encoding="UTF-8"?>
encoding:本XML文件的编码 - XML的标签(元素)规则
·标签由一对尖括号和合法标识组成,必须存在一个根标签,有且只能有一个
·标签必须成对出现,有开始,有结束 如:<name></name>
·特殊标签可以不成对,但必须有结束标记,如:<br/>
·变迁中可以定义属性,属性和标签名用空格隔开,属性值必须用引号引起来,如:<student id = "1" ></name>
·标签需要正确的嵌套,如:1
2
3<student id ="1">
<name>张三</name>
</student> - XML的其他组成
- XML文件中可以定义注释信息:
<!-注释信息-->
- XML文件中可以存在以下特殊字符
<: < 小于
>: > 大于
&: & 和号
&apos: ‘ 单引号
": “ 引号 - XML文件中可以存在CDATA区:
<![CDATA[...内容...]]>
- XML文件中可以定义注释信息:
XML文档约束
- 文档约束:用来限定xml文件中的标签以及属性应该怎么写(以此强制约束程序员必须按照文档约束的规定来编写xml文件)
- 文档约束的分类
- DTD
- 步骤
- 编写DTD约束文档,后缀必须是.dtd
- 在需要编写的XML文件中导入该DTD约束文档
- 按照约束的规定编写XML文件的内容
- 作用
- 可以约束XML文件的编写
- 缺点
- 不能约束具体的数据类型
- 步骤
- schema
- 特点
- schema可以约束具体的数据类型,约束能力更强大
- schema本身也是一个xml文件,本身也收到其他约束文件的要求,所以编写的更加严谨
- 步骤
- 编写schema文档,后缀必须是.xsd
- 在需要编写的XML文件中导入该schema约束文档
- 按照约束内容编写XML文件的标签
- 优点
- 可以约束XML文件的标签内容格式,以及具体的数据类型
- 特点
- DTD
XML解析技术
概述:使用程序读取XML中的数据
两种解析方式
SAX解析:读一行解析一行
DOM解析:一次性读完
Dom常见的解析工具
名称 说明 JAXP SUN公司提供的一套XML的解析API JDOM JDOM是一个开源项目,它基于树型结构,利用纯Java的技术对XML文档实现解析、生成、序列化以及多种操作 dom4j 是JDOM的成绩产品,用来读写XML文档,具有性能优异、功能强大和极易使用的特点,它的性能超过SUN公司官方的dom技术,同时它也是一个开放源代码的软件,Hibrnate也用它来读写配置文件 jsoup 功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便 Dom4j解析XML-得到Document对象
SAXReader类
构造器/方法 说明 public SAXReader() 创建Dom4j的解析器对象 Document read(String url) 加载XML文件成为Document对象 Document类
方法名 说明 Element getRootElement() 获取根元素对象
Dom4j解析XML的元素,属性,文本
方法名 说明 List elements() 得到当前元素下所有子元素 List elements(String name) 得到当前元素下指定名字的子元素返回集合 Element element(String name) 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个 String getName() 得到元素名字 String attributeValue(String name) 通过属性名直接得到属性值 String elementText(子元素名) 得到指定名称的子元素的文本 String getText() 得到文本
XMK索引技术
XPath在解析XML文档方面提供了一独树一帜的路径思路,跟家优雅,高效
XPath使用路径表达式来定位XML文档中的元素节点或属性节点:实例/元素/子元素/孙元素
使用Xpath检索出XML文件步骤
导入jar包(dom4j和jaxen01.1.2.jar),Xpath技术依赖Dom4j技术
通过dom4j的SAXReader获取Document对象
利用XPath提供的API,结合XPath的语法完成选取XML文档元素节点进行解析操作
DOcument中与Xpath相关的API:
方法名 说明 Node selectSingleNode(“表达式”) 获取符合表达式的唯一元素 List selectNodes(“表达式”) 获取符合表达式的元素集合 XPath:绝对路径
·采用绝对路径获取从根节点开始逐层的查找/contactList/contact/name节点类表打印信息方法名 说明 /根元素/子元素/孙元素 从根开始,一级一级向下查找,不能跨级 XPath:相对路径
·先得到根节点contacList
·在采用相对路径获取下一级contact节点的name子节点并打印信息方法名 说明 ./子元素/孙元素 从当前元素开始,一级一级向下查找,不能跨级 XPath:全文搜索
·直接全文搜索所有的那么元素并打印方法名 说明 //contact 找contact元素,无论元素在那里 //contact/name 找contact,无论在哪一级,但name一定是contact的子节点 //contact//name contact无路在哪一种,name只要是contact的子孙元素都可以找到 XPath:属性查找
·在全文中搜索属性,或带属性的元素方法名 说明 //@属性名 查找属性对象,无论是哪个元素,只要有这个属性即可 //元素[@属性名] 查找元素对象,全文搜索指定元素名和属性名 //元素//[@属性名= ‘值’] 查找元素对象,在全文搜索指定元素名和属性名,并且属性值性等
补充
时间格式化:
1 | new SimpleDateFormat(“yyyy/MM/dd HH:mm:ss”).format(time); |
方法递归
- 概述:直接调用自己或间接调用自己
- 注:递归如果没控制好,会出现死循环,导致方法栈内存溢出,从而崩掉
- 一个递归算低至少需要
- 递归公式
- 递归终结点
- 递归放心必须走向终结点
try-catch-finally
·finally:除非jdk崩了,否则一定会执行,return也不能跳过
·finally里不放return,不然会代替其他返回的值,使数据发生错误,开发中不建议使用
集合中数据截取功能
方法名 | 说明 |
---|---|
substring(开始,结束) | 截取从第几个到第几个 |
indexOF(“”) | 取某一个字符 |
设计模式:工厂模式
- 概述:是java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种获取对象的方式
- 作用:
- 工厂的方法可以封装对象的创建细节,比如:为该对象进行加工和数据注入
- 可以实现类与类之间的解耦操作(核心思想)
设计模式:装饰设计模式
- 概述:创建一个新类,包装原始类,从而在新类中提升原来类的功能
- 作用:装饰模式指的是在不改变原类的基础啊上,动态地扩展一个类的功能