JAVA API (application programming interface)
目录
- 第一章 概述
- 第二章 异常类
- 什么是异常?
- Exception的分类
- 出现异常后的反应
- 异常捕获机制
- 异常的抛出
- throws
- throw
- 自定义异常
- 第三章 Math
- 第四章 String和StringBuilder,StringBuffer
- String
- matches() 和正则联系: 正则表达式
- StringBuilder,StringBuffer
- StringBuilder
- 第五章 包装类
- 包装类和基本类型转换
- 包装/基本类型和String转换
- 第六章 Object
- 第七章 集合类
- 集合的分类(重点)
- ArrayList集合
- HashSet集合
- TreeSet集合
- HashMap集合
- TreeMap
- 集合的泛型
- 第八章 工具类
- Collections 集合帮助类
- 第九章 日期类
- Date
- 日期格式转化
- Calendar
- 第十章 精度处理类
- 第十一章 JAVA.io
- 什么是文件?
- File类
- 操作目录的方法(了解)
- 什么是流?
- 流的分类
- 字节型读文件
- 字节型写文件
- 字节型复制
- 字符型读文件
- 字符型写文件
- 缓冲流
- BufferedReader 缓冲输入流
- BufferedWriter 缓冲输出流
- 字节流和字符流适配器
- PrintWriter
- 对象序列化
- InputStream> ObjectInputStream
- OutputStream > ObjectOutputStream
- Properties
- 第十二章 多线程
- 线程的基本概念
- 多线程的创建
- 方式1:继承类:java.lang.Thread
- 方式2:实现接口:java.lang.Runnable
- 线程的状态
- 线程的不同步
- JAVA中线程锁有几种形式
- 死锁
- 线程通讯
- 生产者消费模式
- 线程池
- 线程池使用的API
- 第十三章 JDK8+
- 第十四章 JAVA AWT组件 (了解)
第一章 概述
api 分成以下几个包讲解 :
1.java.lang (异常类, String , Math , StringBuffer,StringBuilder , 包装类 ,Object ,Class 反射 )
2.java.util (日期类,日期转换 ,工具类,BigDecimal , 集合类…)
3.java.io (文件类 文件读写类…)
4.java.net(了解)
5.多线程(lang 重点)
6.java.awt(了解)
7.jdk8+ api (了解API的特性 Stream流)
第二章 异常类
什么是异常?
程序编译或运行当中,出现的问题,统称为异常。异常分为: 程序异常Exception和错误Error。
异常根类: Throwable
程序异常类: Exception 由于程序员疏忽,设计不合理导致的问题,需要解决
程序错误类: Error 程序中出现致命问题如 虚拟机崩溃,内存溢出,堆栈溢出… 不需要在程序中解决
Exception的分类
1.编译时异常: 在程序编译时发生了异常,如果不解决,无法编译
例如: IOException (IO 异常) SQLException(数据库异常) FileNotFoundException(文件未找到异常) …
2.运行时异常 : 编译时没有问题,运行时抛出异常(RuntimeException)
例如:
异常类 | 含义 | 示例 |
---|---|---|
ArrayIndexOutofBoundsException | 数组下标越界异常 |
int[] a = new int[4]; System.out.println(a[4]); |
NullPointerException | 空引用异常 |
String str = null; System.out.println(str.length()); |
ArithmeticException | 数学异常 | 10 / 0 |
ClassCastException | 类型转换异常 | Son s = (Son)new Father(); |
NumberFormatException | 数字转换异常 | Integer.parseInt(“ys”) |
public class TestException1 {public static void main(String[] args) {//数学异常//System.out.println(10 / 0);//数组越界
// int[] a = new int[4];
// System.out.println(a[4]);//空引用
// String str = null;
// System.out.println(str.length());//类型转换
// Son s = (Son)new Father();//数字转换System.out.println(Integer.parseInt("ys") + 10);}
}
出现异常后的反应
1.系统打印错误信息
2.程序终止,突然中断
3.分配对象信息资源不变,可能资源泄露
总结:异常在程序中亟待解决的
异常捕获机制
异常的处理: 异常的捕获机制 (try catch finally)
语法规则:
//监视器
try{//代码监视器,有可能发生异常的代码块
}catch(异常类型 变量名){//异常捕获器,处理问题
}catch(异常类型 变量名){//异常捕获器
} //...
finally{//清理块,无条件执行的语句块
}
注意:
1.try 监视器,不可以单独出现,需要配合catch(可以处理异常)或finally(不会处理异常)
2.catch可以有,捕获不同类型的异常,类似多条分支结果,n选1个,类型不要重复
3.因此将catch(Exception e) {} 放到catch的最后
4.finally 可以写也可以不写,无条件执行,除非退出虚拟机,包括return
public class SystemCode {public static void main(String[] args) {System.out.println("以下张雨代码....");try {System.out.println("..........");System.out.println(10 / 0);}catch(ArithmeticException e) {System.out.println("你发生了数学错误,赶紧改正");//return;//退出虚拟机System.exit(0);}catch(Exception e) {//保底}finally {System.out.println("无条件执行");}System.out.println("张雨代码结束....");System.out.println("以下义民代码....");System.out.println("..........");System.out.println("义民代码结束....");}
}
运行顺序:
情况1:
try {System.out.println(10 / 0);} catch (Exception e) {System.out.println("数学异常");}finally {System.out.println("执行finally");}System.out.println("执行该语句");/**
数学异常
执行finally
执行该语句
*/
情况2:
try {System.out.println(10 / 10);} catch (Exception e) {System.out.println("数学异常");}finally {System.out.println("执行finally");}System.out.println("执行该语句");
/**
1
执行finally
执行该语句
*/
情况3:
try {System.out.println(10 / 0);} finally {System.out.println("执行finally");}System.out.println("执行该语句");/**
执行finally
*/
情况4:
try {System.out.println(10 / 0);} catch (Exception e) {System.out.println("数学异常");return;}finally {System.out.println("执行finally");}System.out.println("执行该语句");/**
数学异常
执行finally
*/
注意: 先执行finally ,再执行return
情况5:
try {System.out.println(10 / 0);} catch (Exception e) {System.out.println("数学异常");System.exit(0);}finally {System.out.println("执行finally");}System.out.println("执行该语句");/**
数学异常
*/
异常的抛出
throw和throws
throws
当方法内有异常发生,不解决,难以解决时,将方法内的异常向外抛出,使用throws。
语法:
控制权限 返回值 方法名(参数类型 参数变量) throws 异常类型1, 异常类型2... {//有异常}
注意:
- 方法的异常抛给方法的调用者,调用者必须解决或继续抛,直到主方法,主方法抛给虚拟机
public class TestThrows {//方法向外抛出异常public static void test1() throws NullPointerException,ArithmeticException{ System.out.println(10 / 0);}//调用后不解决,继续抛public static void test2() throws Exception{ test1();}public static void main(String[] args) {try {//调用者test1();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
- 方法重写时,子类不允许抛出更大类型异常
public class A {public void test() throws NullPointerException{}
}class B extends A{//重写不能抛出更大类型
// public void test() throws Exception{//
// }//重载不限制public void test(int a) throws Exception{}
}
- 一般都是编译时异常抛出
- throws 抛出异常类
throw
当程序员需要手动创造一个异常,并且抛出去。自己构建一个异常。
语法:
//1 创建一个异常对象
Exception 对象名 = new Exception("异常的问题");
//2 throw抛出
throw 对象名;
例子:
public class TestThrow {public static void main(String[] args) {//使用检测年龄方法checkAge(9);System.out.println("继续编码代码");}/*** 检测年龄是否合法*/public static void checkAge(int age) {if(age > 0 && age < 150) {System.out.println("年龄合法");}else {//构建异常RuntimeException e = new RuntimeException("年龄不合法,不能超出(1-150)");//手动抛出异常throw e;}}
}
throws 和 throw 区别?
throws | throw | |
---|---|---|
方法向外自动抛出异常 | 手动创建异常抛出 | |
异常类 | 异常对象 | |
方法后面 | 方法里 |
自定义异常
程序员自己构建一个异常类型,需要继承异常父类: RuntimeException或者Exception。
public class AgeException extends Exception{/*** 序列号*/private static final long serialVersionUID = 1L;public AgeException() {super();// TODO Auto-generated constructor stub}public AgeException(String message) {super(message);// TODO Auto-generated constructor stub}}/*** 检测年龄是否合法* @throws AgeException */public static void checkAge(int age) throws AgeException {if(age > 0 && age < 150) {System.out.println("年龄合法");}else { throw new AgeException("年龄非法");}}
第三章 Math
Math 类包含用于执行基本数学运算的方法。
注意:
- Math是final修饰的类,并不能拓展子类
- Math构造方法是私有的,所有属性和方法全是静态的 Math.属性 Math.方法
构造:构造被私有化
属性:
属性 | ||
---|---|---|
PI | 圆周率 | public static final double |
E | 自然底数 | public static final double |
方法:
方法 | 含义 | 返回值或参数 |
---|---|---|
random() | 随机数 | [a,b] : (int)((b - a + 1) * Math.random() + a) |
ceil(double) | 向上取整 | 获得比当前参数稍微大的整数,如果就是整数返回自己 |
floor(double) | 向下取整 | 获得比当前参数稍微小的整数,如果就是整数返回自己 |
round(double) | 四舍五入 | 返回四舍五入结果(整数位),注意:Math.floor(a + 0.5f) |
sqrt(double) | 开平方根 | NaN : not a number |
pow(a,b) | a的b次幂 | b个a相乘 |
案例1:随机生产 四个大写字母(验证码)
char [] code = new char[4];for (int i = 0; i < code.length; i++) {code[i] = (char)((90 - 65 + 1) * Math.random() + 65);for (int j = 0; j < i; j++) {if(code[j] == code[i]) {i --;break;}}}
System.out.println(Arrays.toString(code));
案例2: 猜数游戏
public class TestMath{public static void main(String[] args) {int num = (int) ((100 - 50 + 1) * Math.random() + 50);Scanner sc = new Scanner(System.in);int s = 50, e = 100;for (int i = 0; i < 5; i++) {System.out.println("第" + (i + 1) + "次机会请输入你猜的数字(" + s + "-" + e + ")");int m = sc.nextInt();if (num > m) {System.out.println("猜小了");s = m;} else if (num < m) {System.out.println("猜大了");e = m ;} else {System.out.println("Win");return;}}System.out.println("机会用完了,数字是:" + num);}
}
取整和四舍五入的案例:
//向上取整System.out.println(Math.ceil(12.5));//13.0System.out.println(Math.ceil(12));//12.0System.out.println(Math.ceil(-8.01));//-8.0System.out.println(Math.ceil(-7.92)); // -7.0System.out.println("-----------------");//向下取整System.out.println(Math.floor(12.98)); //12.0System.out.println(Math.floor(-12.98));//-13.0System.out.println(Math.floor(14));//14.0//Math.floor(a + 0.5f) //四舍五入System.out.println(Math.round(12.67)); //13System.out.println(Math.round(-12.67)); // -13System.out.println(Math.round(12.27)); //12System.out.println(Math.round(2.5));//3//特殊的System.out.println(Math.round(-2.5));//-2
开方和次幂:
//开平方System.out.println(Math.sqrt(25));System.out.println(Math.sqrt(-36));//NaN //求次幂System.out.println(Math.pow(3, 4));// 3 * 3 * 3 * 3
第四章 String和StringBuilder,StringBuffer
String
不可变字符串,一经定义不能改变。 " "括起来的,原样的。
注意: 字符串对象和字符串常量"abc" 都认为是对象型
String s = "abc123中";//字符串常量也是对象System.out.println(s.length());System.out.println("abcd".length());
构造方法:
new String();
new String("abc");
new String(StringBuilder sbl); //将可变字符串Builder转为String
//一共创建三个对象
String s1 = new String("abc");
String s2 = new String("abc");String s3 = "abc";
String s4 = "abc";
System.out.println(s1 == s2);//false
System.out.println(s3 == s4);//true
使用 | 方法名 | 含义 | 返回值 |
---|---|---|---|
长度 | 字符串.length() | 字符串长度,汉字按照1个 | 返回字符个数 |
查找单个 | 字符串.charAt(下标) | 字符串有下标,从0,对应下标的一个字符 | 一个字符 |
截取 | 字符串.substring(下标) | 从下标截取到最后 | 截取的新的子串 |
截取区间 | 字符串.substring(起始下标,结束下标) | 从起始下标截取到结束下标-1 | 同上 |
分割 | 字符串.split(切割符号) | 字符串分割,注意特殊符号要加转义 | 字符串数组 |
查找子串 | 字符串.indexOf(子串) | 从字符串中查找是否存在子串(左向右) | 返回第一次下标,不存在返回-1 |
查找子串 | 字符串.lastIndexOf(子串) | 从字符串中查找是否存在子串 | 返回最后一次下标,不存在返回-1 |
比较内容 | 字符串.equals(参数串) | 参数串和字符串内容相同,不管地址 | boolean |
比较顺序 | 字符串.compareTo(参数串) | 比较字典顺序 | 0 (相同)负的 正的 |
替换 | 字符串.replace(old,new) | 将old替换成new | 新串 |
正则校验 | 字符串.matches(正则) | 匹配正则表达式 | |
字符串.endsWith() | |||
字符串.startsWith() | |||
字符串.trim() | 去掉两端空白 |
截取案例:
public class TestString2 {public static void main(String[] args) {String str = "abcd中国人";//长度//System.out.println("abcd中".length());//获得一个字符//System.out.println(str.charAt(4)); //System.out.println(str);//截取String s1 = str.substring(4);System.out.println(s1); System.out.println(str.substring(0, 4)); System.out.println(str);}
}
分割和查找案例:
public class TestString3 {public static void main(String[] args) {String city = "大连|本溪|丹东|辽阳";//分割String[] citys = city.split("\\|");for (String c : citys) {System.out.println(c);}String str = "abacdabddfgr";//字符串查找//第一次出现位置System.out.println(str.indexOf("ys"));//最后一次出现位置System.out.println(str.lastIndexOf("ab"));}
}
字符串比较:
public class TestString4 {public static void main(String[] args) {String str = "abcdabff";//字符串替换System.out.println(str.replace("ab", "*"));System.out.println(str);String s1 = "bdc";String s2 = new String("bdcd");//字符串比较内容//System.out.println(s1 == s2);//false//System.out.println(s1.equals(s2));//true//字符串比较顺序System.out.println(s1.compareTo(s2));}
}
matches() 和正则联系: 正则表达式
正则表达式: 相当于定义了一个规范格式,匹配的模型,衡量标准。
字符串.matches(正则表达式); // 满足返回true 否则返回false
1.正则的开始 ^
2.正则的结束 $
3.正则的内容 区间 [abc] a,b,c任选一个 [a-z] a-z任选一个 直接匹配: @qq.com 0411-
4.正则的位数 {n} 就是n位 {n,m} n到m位 {n,} n位以上
5.简化 \d [0-9] \w [0-9a-zA-Z_]
6.特殊位数: + 1个或多个; ? 0或1个 ; * 0或多个
7.或者 |
正则案例:
public class TestPartten2 { /*** 1. 正则检测账号 : 首位必须字母,其余是字母数字_ 8-10位*/ public static boolean checkNo(String no) { return no.matches("^[a-zA-Z]{1}\\w{7,9}$"); } /*** 2. 正则检测身份证* @param no* @return*/public static boolean checkCard(String id) { return id.matches("^[1-8]{1}\\d{16}[0-9X]$"); } /*** 检测手机号* @param args*/public static boolean checkTel(String tel) { return tel.matches("^(138\\d{8})|(159\\d{8})$"); } public static void main(String[] args) {//System.out.println(checkCard("210283200205091013"));}
}
StringBuilder,StringBuffer
都是可变字符串,在原字符串基础上,增删改,字符串的缓冲。
总结:
String: 不可变字符串,不能改变
StringBuilder可变字符串,线程不安全,不同步,效率高,推荐。
StringBuffer 可变字符串,线程安全,同步的,效率低
StringBuilder
可变的字符序列,相当于字符串的缓冲区,可以改变的。
构造方法:
new StringBuilder(); //创建默认的字符串缓冲区 16字符
new StringBuilder(int);// 创建指定容量的缓冲区
new StringBuilder(String);// 创建字符串缓冲区,存入默认字符串,将String变成Builder
public class TestBuilder {public static void main(String[] args) {StringBuilder b1 = new StringBuilder();//16 StringBuilder b2 = new StringBuilder(10);//25 StringBuilder b3 = new StringBuilder("abc");////字符串长度System.out.println(b1.length());System.out.println(b2.length());System.out.println(b3.length()); //缓冲区容量System.out.println(b1.capacity());System.out.println(b2.capacity());System.out.println(b3.capacity());}
}
常用方法:
方法名 | 含义 | 返回值 |
---|---|---|
length() | 字符串长度,内容个数 | int |
capacity() | 缓冲区大小,容量 | int |
append(字符串) | 在原串尾部追加字符串 | StringBuilder |
insert(下标,字符串) | 在该下标前插入字符串 | StringBuilder |
deleteCharAt(下标) | 根据下标删除一个字符 | StringBuilder |
delete(s,e) | 从s删除到e-1 | StringBuilder |
setCharAt(下标,修改字符) | 对应下标修改一个 | StringBuilder |
reverse() | 翻转 | StringBuilder |
追加:
//粘贴26个字母
StringBuilder bul = new StringBuilder();
for (char i = 'a'; i <= 'z'; i++) {bul.append(i);
}
System.out.println(bul);
其余方法:
public class TestBuilder3 {public static void main(String[] args) {StringBuilder bul = new StringBuilder("中国人"); //下标1左侧插入华人民bul.insert(1, "华人民"); bul.insert(bul.indexOf("国"), "共和"); //删除最后一个bul.deleteCharAt(bul.length() - 1);//删除区间//bul.delete(0, 4);//人修改为义bul.setCharAt(2, '义');//翻转bul.reverse();System.out.println(bul);}
}
使用翻转做回文数:
public static boolean isHui(String str) {StringBuilder bul = new StringBuilder(str);//判断翻转的和原来是否对等if(str.equals(bul.reverse().toString())) {return true;}else {return false;}}
第五章 包装类
包装类
八个类和八个基本数据类型对应的类,将每个离散的数据类型包装成类型。
包装类 | 基本类型 |
---|---|
Byte | byte |
Short | short |
Integer | int |
Long | long |
Float | float |
Double | double |
Character | char |
Boolean | boolean |
包装类和基本类型转换
装箱: 将基本数据类型转化为包装类
//手动装箱(JDK5-)
//new Integer(int);//自动装箱(JDK5+)
int a = 10;
Integer i = a;
//注意,不能用自动转换
//Long l = a;//错误的用法
//自动装箱时,必须满足左右两侧一致
拆箱: 将包装类转化为基本数据类型
//手动拆箱(JDK5-)
//对象.intValue();
//自动拆箱(JDK5+)
Integer i = 10;
int a = i;
包装/基本类型和String转换
1.其他类型转化为String
//1.拼接 + concat()
int a = 10;
System.out.println(a + "");
//2.转化为包装对象
Integer i = a;
System.out.println(i.toString());
//3 valueOf()
String.valueOf(d)
2.String转化为其他类型(开发中需要使用)
String s = "10";
Integer.parseInt(s);//转int
String s2 = "10.3";
Double.parseDouble(s2); //转double
第六章 Object
Object所有类的根类,所有类都继承该类
构造方法:
new Object(); 为子类调用
方法:
方法 | 含义 | 返回值 |
---|---|---|
finalize() | 垃圾回收方法,JVM自行调用,无需手动调用 | |
hashCode() | 返回对象的哈希值,根据哈希表提供的 | |
toString() | getClass().getName() + ‘@’ + Integer.toHexString(hashCode()) | |
wait() | ||
notify() |
注意:
final 修饰符 最后的
finally{} 语句块 异常中无条件执行
finalize() 方法,所有对象存在的,垃圾回收
第七章 集合类
java.util.*
集合的概念
集合作为JAVA中数据存储介质,和数组不同的是:
- 集合中的元素类型可以不一样(默认每个元素Object)
- 集合的大小可变,可以扩容的,方便增删改
集合的分类(重点)
系列1:(Collection接口: 存储值)
List子接口: 有下标,0开始,顺序
ArrayList 实现类: 线性存储结构,元素挨着, 适合查询,不适合更新,线程不安全,效率高,不同步,速度快
LinkedList 实现类: 链式存储结构,元素不挨着,适合更新,不适合查找
Vector 实现类: 线程安全,效率低,同步
Set子接口: 没有下标,不能保证顺序,吞并重复元素
HashSet 实现类 : 哈希表存储 自动去重
TreeSet 实现类 : 红黑树存储 可以自然排序
系列2:(Map接口:存键值对 )
HashMap 实现类: 线程不安全,效率高,不同步,速度快
Hashtable 实现类: 线程安全,效率低,同步
TreeMap 实现类 : 自然排序
ArrayList集合
可变容量的数组,随着元素的增加而扩充容量,线性存储结构,List的实现类,该类是有下标,下标从0开始。
底层有容量判断机制,自动扩容。
构造方法:
new ArrayList(); //空构造
new ArrayList(Collection c);//使用多态构建集合
方法:
方法名 | 含义 | 返回值 |
---|---|---|
add(元素) | 尾部追加 | 布尔 |
add(下标,元素) | 在下标前插入元素 | 无 |
size() | 集合大小 | int |
remove(下标) | 根据下标删除元素 | E |
remove(元素) | 根据元素删除 | boolean |
get(下标) | 根据下标获得一个元素 | E |
set(下标,元素) | 根据下标修改元素 | 无 |
clear() | 清除集合 | |
indexOf()/lastIndexOf() | 元素查找 | int -1 |
注意:
当使用remove()的时候,传入参数int型,默认认为是下标。
集合的方法案例:
public class TestList1 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();//追加元素list.add(20);list.add(40);list.add(60);list.add(80);//在60前插入88//list.add(2,88); //打印大小//System.out.println(list.size());//list.remove(20); 下标20//装箱删除//list.remove(new Integer(20));//该类覆盖toString()//System.out.println(list.toString());//System.out.println(list.get(0));//修改list.set(list.size() - 1, 100);
}
集合的遍历:
//遍历集合 get()获得元素for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}//foreachfor (Integer a : list) {System.out.println(a);}
HashSet集合
没有下标的线性集合,不能保证元素的顺序,会自动去重,内存: 哈希表
构造方法:
new HashSet();
new HashSet(Collection c);
方法:
方法名 | 含义 | 返回值 |
---|---|---|
add() | 尾部增加,不能插入 | |
remove(元素) | 删除对应元素 | |
size() | 大小 | |
iterator() | 返回该集合的迭代器(专门用于Collection元素遍历) |
迭代器接口:Iterator 很多集合实现类都实现了该接口
方法 | 含义 | 返回值 |
---|---|---|
hasNext() | 是否有迭代元素 | boolean |
next() | 取出下一个元素 | E |
案例:
public class TestSet1 {public static void main(String[] args) {Set<String> set = new HashSet<>();set.add("jack");set.add("rose");set.add("tom");//重复元素无法添加set.add("jack");//删除//set.remove("rose");set.remove("ys");System.out.println(set.size());System.out.println(set);}
}
合并去重:
public class TestSet2 {public static void main(String[] args) {//两个数组合并 且去掉重复int[] a = {12,45,23,77,83,45,7};int[] b = {42,65,23,57,88};//创建HashSetHashSet<Integer> set = new HashSet<>();for (int i = 0; i < a.length; i++) {set.add(a[i]);}for (int i = 0; i < b.length; i++) {set.add(b[i]);}System.out.println(set);}
}
set集合的遍历:
//创建集合
Set<String> set = new HashSet<>();//添加元素set.add("jack");set.add("rose");set.add("tom");set.add("ys");
//foreach
for (String s : set) {System.out.println(s);
}
//迭代器
//获得集合的迭代器
Iterator<String> it = set.iterator();
//判断是否存在元素
while(it.hasNext()) {//获取并打印System.out.println(it.next());
}
TreeSet集合
内存存储:红黑树(平衡二叉树), 存储的元素会实现自然排序(得有排序算法)。
构造方法:
new TreeSet();
new TreeSet(Collection c);//传其他其他
new TreeSet(Comparator c);//传入比较器,比较算法
方法:
方法 | 含义 | 返回值 |
---|---|---|
add(元素) | 添加 | |
size() | 集合大小 |
Integer,String自动实现了排序算法:
// TreeSet<Integer> tree = new TreeSet<Integer>();
//
// tree.add(12);
// tree.add(72);
// tree.add(53);
// tree.add(8);
// tree.add(46);// TreeSet<String> tree = new TreeSet<>();
// tree.add("apple");
// tree.add("peach");
// tree.add("banana");
// tree.add("orange");
水果类型需要自行添加比较算法:
比较机制:
Comparator 比较器,决定如何比较
Comparable 比较标志,实现了该接口的类能够自然排序。
public class Fruit implements Comparable<Fruit>{private int fNo;private String fName;private double price;private int counts;public int getfNo() {return fNo;}public void setfNo(int fNo) {this.fNo = fNo;}public String getfName() {return fName;}public void setfName(String fName) {this.fName = fName;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public int getCounts() {return counts;}public void setCounts(int counts) {this.counts = counts;}public Fruit(int fNo, String fName, double price, int counts) {super();this.fNo = fNo;this.fName = fName;this.price = price;this.counts = counts;}public Fruit() {}@Overridepublic String toString() {return "Fruit [fNo=" + fNo + ", fName=" + fName + ", price=" + price + ", counts=" + counts + "]";}@Overridepublic int compareTo(Fruit o) {if(o.getPrice() == this.price) {return 0;}if(o.getPrice() > this.price) { return -1;}else {return 1;} }
}
TreeSet<Fruit> tree = new TreeSet<Fruit>();tree.add(new Fruit(1, "苹果", 5, 300));tree.add(new Fruit(2, "香蕉", 3, 100));tree.add(new Fruit(4, "法国香蕉", 3, 100));tree.add(new Fruit(3, "桃子", 8, 200));for (Fruit fruit : tree) {System.out.println(fruit);}
HashMap集合
Map系列的集合,HashMap和Hashtable区别?
- HashMap线程不安全,效率高,速度高,不同步。
- HashMap支持键和值可以为null的。
HashMap集合特点:存储键值对 key-value
构造方法:
new HashMap<K,V>();
方法:
方法名 | 含义 | 返回值 |
---|---|---|
put(键,值) | 添加元素/修改元素 | V |
size() | 集合大小 | int |
get(键) | 通过键取对应值 | V |
remove(键) | 通过键删除整个键值对 | V |
containsKey(键) | 判断是否存在这个键 | boolean |
keySet() | 以Set集合形式返回key集合(遍历) | Set |
注意:put的两个用法:键不同是增加元素,键相同修改元素
public class TestMap {public static void main(String[] args) {HashMap<String, String> map = new HashMap<String, String>();//添加map.put("username", "diana");map.put("password", "123456");map.put("ip", "192.168.1.1");//修改map.put("ip", "192.168.168.10");map.put("ip2", "192.168.1.1");//集合大小//System.out.println(map.size());//System.out.println(map);//根据键获得值System.out.println(map.get("password"));//删除元素map.remove("ip2");System.out.println(map);}
}
map集合的遍历:先找到所有的key,通过每一个key获得对应的value
public class TestMap2 {public static void main(String[] args) {HashMap<String, String> map = new HashMap<String, String>();//添加map.put("username", "diana");map.put("password", "123456");map.put("ip", "192.168.1.1");//先找到所有的keySet<String> keys = map.keySet();//遍历key集合 获得值for (String k : keys) {System.out.println(k + "=" + map.get(k));}//获得迭代器Iterator<String> it = keys.iterator();while(it.hasNext()) {String k = it.next();System.out.println(k + "=" + map.get(k));}}
}
给定数组,统计数组中出现次数最多的元素:
public class TestMap3 {public static void main(String[] args) {int[] a = {12,56,34,77,6,34,1,77,99,34,77};HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();for (int i = 0; i < a.length; i++) {//是否存在if(map.containsKey(a[i])) {//存在map.put(a[i], map.get(a[i]) + 1);}else {map.put(a[i], 1);}}System.out.println(map);}
}
TreeMap
存储:红黑树,自然排序(Comparator比较器;使用键提供排序,键类型必须实现Comparable)。
集合的泛型
- 泛型的基本概念: JDK5+新增的泛型,泛指的类型,参数化类型
- 泛型的好处:避免大量的类型转化,增加代码的灵活性,类型像参数一样可以传递
- 三种表现形式:1.泛型接口 比如(Comparator)
<T>
2.泛型类3.泛型方法 - 语法:
<T> T可以是任意类型 Integer ,Double ,String ,Student<K,V> K,V 分别是键值对的两种类型
- 泛型类
public class MyGeneric<T> {private T t;/*** 方法*/public T getT(T t) {return t;}
}
测试泛型:
public class TestGeneric2 {public static void main(String[] args) {MyGeneric<Integer> my = new MyGeneric<Integer>();Integer a = my.getT(10);System.out.println(a);}
}
泛型接口:
由于接口中常量是静态常量,必须给初始化,因此泛型不可以做静态常量。
public interface MyGeneric2<T> {//public static final T t ;public abstract void getT(T t1, T t2) ;
}
测试接口:
public class TestGeneric4 {public static void main(String[] args) {MyGeneric2<String> gen = new MyGeneric2<String>() {@Overridepublic void getT(String t1, String t2) {System.out.println(t1.length() - t2.length());}};gen.getT("ys8888", "diana");}
}
第八章 工具类
Scanner 控制台接收
Array 数组的帮助类
方法名 | 含义 | 返回值 |
---|---|---|
asList(T…a) | 将数组转化为集合 |
List<T>
|
public class TestArray {public static void main(String[] args) {//将数组转化为集合List<Integer> list = Arrays.asList(10,20,10,45,12,78,34);//去重//HashSet<Integer> set = new HashSet<Integer>(list);TreeSet<Integer> set = new TreeSet<>(list);System.out.println(set);}
}
Collections 集合帮助类
Collection : 集合的上层接口 ,集合系列
Collections : 集合的帮助类,包含操作集合的方法,类似于 Arrays
public class TestCollections {public static void main(String[] args) {//将数组转化为集合List<Integer> list = Arrays.asList(10,20,10,45,12,78,34);//最大值System.out.println(Collections.max(list));//排序Collections.sort(list);System.out.println(list);//翻转Collections.reverse(list);System.out.println(list);//二分查找 先排序int i =Collections.binarySearch(list, 145); if(i >= 0) {System.out.println("有");}else {System.out.println("没有");}}
}
第九章 日期类
Date
日期类,操作日期,java.util.Date 还有java.sql.Date,其中java.util.Date是父类。
构造方法:
new Date(); // 创建系统当前时间
new Date(long); //传入一个时间差,返回具体时间点
方法:
方法名 | 含义 | 返回值 |
---|---|---|
getTime() | 距离1970.1.1时间差 | long |
public class TestDate {public static void main(String[] args) {Date date = new Date(); System.out.println(date);}
}
日期格式转化
SimpleDateFormat:日期格式化
构造方法:
new SimpleDateFormat(时间格式) ;
方法:
方法名 | 含义 | 返回值 |
---|---|---|
parse() | 字符串转化为日期 | Date |
format() | 日期转化为字符串 | String |
public class TestDate { public static void main(String[] args) throws ParseException {Date date = new Date();
// System.out.println(date);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");System.out.println(sdf.format(date));String ss = "2022-6-8";SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");Date date2 = sdf2.parse(ss);//System.out.println(date2.getDate());}
}
格式化:
Calendar
日历类,是一个抽象类,不能new。使用的时候需要调用方法 getInstabce()返回一个通用日历对象。
方法:
方法 | 含义 | 返回值 |
---|---|---|
getInstance | 返回一个实例 | Calendar |
set(参数) | 设置日期和时间 | |
get(常量) | 获得指定域的值 |
public class TestCalendar {public static void main(String[] args) {Calendar c = Calendar.getInstance();//月c.set(2022, 7, 1); System.out.println(c.get(Calendar.YEAR));System.out.println(c.get(Calendar.MONTH));System.out.println(c);}
}
第十章 精度处理类
用于处理精度问题的类:BigDecimal,精度不可避免,特殊处理。
构造方法:
new BigDecimal(String opr1);
方法名 | 含义 | 返回值 |
---|---|---|
add() | 加 | BigDecimal |
subtract() | 减 | BigDecimal |
multiply | 乘 | BigDecimal |
divide | 除 | BigDecimal |
例子:
double d1 = 4.9;
double d2 = 2.0;
//存在精度问题
System.out.println(d1 - d2);BigDecimal b1 = new BigDecimal(d1 + "");
BigDecimal b2 = new BigDecimal(d2 + "");
//处理精度
System.out.println(b1.subtract(b2));
//运算表达式
System.out.println((4.8 - 3.2) * 0.2);
//处理
BigDecimal m1 = new BigDecimal("4.8");
BigDecimal m2 = new BigDecimal("3.2");
BigDecimal m3 = new BigDecimal("0.2");
System.out.println(m1.subtract(m2).multiply(m3));
第十一章 JAVA.io
io:input output 输入输出,出现最高的异常:IOException,FileNotFoundException。
什么是文件?
相关记录构成的数据集都是文件:文本文档,图像,压缩包,硬盘,光盘…都是文件。文件可以持久化数据。弊端是共享性比较差
File类
用于操作文件和目录(文件夹),
构造方法:
new File("E:\\1.txt");//操作文件
new File("E:\\a"); //操作文件夹
操作文件的方法(了解)
方法名 | 含义 | 返回值 |
---|---|---|
exists() | 文件是否存在 | |
length() | 文件长度 | |
lastModified() | 最后修改时间差 | long |
createNewFile() | 新建文件 | |
delete() | 删除文件 |
public class TestFile {public static void main(String[] args) throws IOException {File f1 = new File("d:\\2.txt");if(f1.exists()) {System.out.println("存在该文件");}else {f1.createNewFile();}System.out.println("长度:" + f1.length());System.out.println("路径" + f1.getPath());System.out.println("名字" + f1.getName());System.out.println(f1.canRead());SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("最后修改时间:" + sdf.format(new Date(f1.lastModified())));f1.delete();}
}
操作目录的方法(了解)
方法名 | 含义 | 返回值 |
---|---|---|
mkdirs() | 无需父目录,连带创建目录 | |
mkdir() | 父目录存在 | |
listFiles() | 列举目录的内容 | File[] |
isDirectory | 判断是否是文件夹 | boolean |
delete() | 必须删除空目录 |
package com.qf.api;import java.io.File;public class TestFile2 {public static void main(String[] args) {File f = new File("D:\\m");//创建文件夹//f.mkdirs();//调用方法列举内容//getAll(f);f.delete();}/*** 方法: 传入文件夹,获得所有内容*/public static void getAll(File f) {System.out.println("目录:" + f.getName());//列举文件夹中内容File[] files = f.listFiles();for (File file : files) {if(file.isDirectory()) {//文件夹,递归getAll(file); }else {System.out.println("文件:" + file.getName());}} }/*** 方法: 传入文件夹,删除该文件夹*/
}
流(文件的输入输出)
什么是流?
一脸串的数据信号,数据管道,连接桥梁,称之为流。
流的分类
- 流的方向(输入输出流,参照物:你)
输入流:读文件,从文件中读取,向程序端输入
输出流:写文件,从程序一端输出写入文件
- 文件类型
1.文本文件 字符型文件 .txt .java (根类:Reader读 Writer写)
2.二进制文件 字节型文件 .doc .mp4 .excel (根类InputStream读 OutputStream写)
- 流的流通量
节点流
缓冲流(处理流) 效率高
字节型读文件
InputStream > FileInputStream
构造方法:
new FileInputStream(String name);
new FileInputStream(File f);
方法:
方法名 | 含义 | 返回值 |
---|---|---|
read() | 每次读一个字节 | int 没有返回 -1 |
close() | 关闭流相关资源 | |
read(byte[]) | 每次读一个数组长度 |
案例:字节型文件的读
public class TestInputStream {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("d:\\1.txt");int r = fis.read();while(r != -1) {System.out.println((char)r);//再读一个r = fis.read();}//关闭fis.close();}
}
字节型写文件
OutputStream > FileOutputStream
构造方法:(写入的时候,文件可以不存在,自动创建)
new FileOutputStream(File file, boolean append) ; //追加写
new FileOutputStream(File file) ; //覆盖写
方法:
方法名 | 含义 |
---|---|
write() | 每次写一个字节 |
close() | 关闭流相关资源 |
注意:\n 或使用 \r \n
案例:
public class TestOutputStream {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream(new File("D:\\2.txt"),true);fos.write('y');fos.write('s');//fos.write('\r');fos.write('\n');fos.write('w');fos.write('e');fos.write('l');fos.write('c');fos.write('o');fos.write('m');fos.write('e'); //关闭流fos.close();}
}
字节型复制
/*** 字节型文件的复制* * @author 86136**/
public class TestCopy {public static void main(String[] args) throws IOException {//系统时间long time1 = System.currentTimeMillis();FileInputStream fis = new FileInputStream("D:\\1.zip");FileOutputStream fos = new FileOutputStream("D:\\3.zip");int i = fis.read(b,0,b.length);while(i != -1) {fos.write(b,0,b.length);i = fis.read(b,0,b.length);}//系统时间long time2 = System.currentTimeMillis();//差System.out.println(time2 - time1);//关闭资源fis.close();fos.close();}
}
字符型读文件
Reader > InputStreamReader > FileReader 字符型输入流
构造方法:
new FileReader(String name);
new FileReader(File f);
方法:
同FileInputStream,区别是可以读字符。
public class TestReader {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("D:\\1.txt");int r = fr.read();while(r != -1) {System.out.print((char)r);r = fr.read();}fr.close();}
}
字符型写文件
Writer > OutputStreamWriter > FileWriter 字符型输出流
构造方法;
new FileWriter(String name);
new FileWriter(File f,boolean append);
方法:
方法名 | 含义 | |
---|---|---|
write(String s) | 每次写入一个字符串 | |
close() | 关闭流相关资源 | |
write(int i) | 每次写一个字符 | |
append(字符串) | 追加内容 |
缓冲流
节点流: 直接和文件打交道的流
缓冲流: 处理流,对节点流处理,不会直接操作文件。加快读写效率,方便流操作。
BufferedReader 缓冲输入流
BufferedWriter 缓冲输出流
构造方法:
new BufferedReader(Reader r) ;
new BufferedWriter(Writer w) ;
方法:
方法名 | 含义 | |
---|---|---|
readLine() | 每次读一行 | |
close() | 关闭所有连带的相关资源 | |
write(String s) | 每次写入一串 | |
newLine() | 换行 | |
flush() | 刷新,关闭前先刷新 |
public class TestBufferedReader {public static void main(String[] args) throws IOException {//节点流FileReader fr = new FileReader("d:\\5.txt");//缓冲流BufferedReader br = new BufferedReader(fr);//读一行String r = br.readLine();while(r != null) {System.out.println(r);//再读一行r = br.readLine();}br.close();}
}
public class TestBufferedWriter {public static void main(String[] args) throws IOException {//节点流FileWriter fr = new FileWriter("d:\\6.txt");//缓冲流BufferedWriter br = new BufferedWriter(fr);br.write("哈哈哈哈");br.newLine();br.write("哼哼哼");br.flush();br.close();}
}
文件复制:
package com.qf.api;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;public class TestCopy2 {public static void main(String[] args) throws IOException {// 节点流FileReader fr = new FileReader("d:\\从红月开始.txt");// 缓冲流BufferedReader br = new BufferedReader(fr);// 节点流FileWriter fw = new FileWriter("d:\\copy.txt");// 缓冲流BufferedWriter bw = new BufferedWriter(fw);int count = 0;String r = br.readLine();while (r != null) {++count;if (count >= 1 && count <= 9) {bw.write("000" + count +"\t" + r);} else if (count >= 10 && count <= 99) {bw.write("00" + count +"\t" + r);} else if (count >= 100 && count <= 999) {bw.write("0" + count +"\t" + r);} else {bw.write(count +"\t" + r);}//换行bw.newLine();r = br.readLine();}br.close();bw.flush();bw.close();}
}
字节流和字符流适配器
字节流向字符流转化:InputStreamReader,字节流通向字符流的桥梁。
构造方法:
new InputStreamReader(字节流); //构建完后成为字符流
/**字节向字符转化的桥梁
*/
public class TestSystem {public static void main(String[] args) throws IOException {//Scanner sc = new Scanner(System.in);System.out.println("请输入内容:");//字节流InputStream is = System.in;//字符流InputStreamReader isr = new InputStreamReader(is);//加缓冲BufferedReader br = new BufferedReader(isr);String r = br.readLine();System.out.println("您输入的是:" + r);br.close();//sc.close();}
}
PrintWriter
文本输出打印流:
特点:
- 自动创建文件
- 自带缓冲
- 自动换行
- 自带刷新
构造方法:
new PrintWriter(OutputStream out, boolean autoFlush) ;//自动刷新
new PrintWriter(OutputStream out) ;
方法:
方法名 | 含义 | 返回值 |
---|---|---|
println() | 输出并换行 | |
print() | 输出不换行 | |
close() | 关闭流 | |
format() | 输出打印的,格式化要求 |
public class TestPrintWriter {public static void main(String[] args) throws IOException {PrintWriter pw = new PrintWriter("d:\\1.txt");pw.println("中国人民解放军"); pw.println("我爱中国"); pw.format("%04d", 10);pw.flush();pw.close();}
}
案例:存入学生分数到文件中
public class TestPrintWriter2 {public static void main(String[] args) throws IOException {PrintWriter pw = new PrintWriter("d:\\score.txt");Scanner sc = new Scanner(System.in);System.out.println("请录入分数:");String score = sc.next();while(!score.equals("end")) {//写入pw.println(score);//继续接收System.out.println("请录入分数:");score = sc.next();}System.out.println("停止接收");pw.flush();pw.close();}
}
获得学生分数,求和
public class TestScore {public static void main(String[] args) { int sum = 0;BufferedReader br = null;try {FileReader fr = new FileReader("d:\\score.txt");br = new BufferedReader(fr);String score = br.readLine();while(score != null) {sum += Integer.parseInt(score);score = br.readLine();}System.out.println("总分:" + sum);} catch (NumberFormatException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {br.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
对象序列化
对象序列化和反序列化: 对象持久化,将JAVA中对象持久存入到文件中,当需要的时候,再从文件中读取出来。
对象序列化: 将对象写入到文件中
对象反序列化: 将对象从文件中读出来
InputStream> ObjectInputStream
OutputStream > ObjectOutputStream
注意:
类通过实现 java.io.Serializable
接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
构造方法:
new ObjectInputStream(InputStream is);// 反序列化对象
new ObjectOutputStream(OutputStream os);//序列化对象
方法:
writeObject(对象); //写入对象
(Student)ois.readObject();//读取对象
实体类:
public class Student implements Serializable{private int sno;private String sname;public int getSno() {return sno;}public void setSno(int sno) {this.sno = sno;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public Student(int sno, String sname) {super();this.sno = sno;this.sname = sname;}public Student() {}}
序列化:
public class TestObject1 {public static void main(String[] args) throws IOException {Integer t1 = 20;String a = "abc";Student s = new Student(1,"jack");FileOutputStream fos = new FileOutputStream("d:\\info.txt");//序列化ObjectOutputStream oos = new ObjectOutputStream(fos);//将对象写入到文件oos.writeObject(t1);oos.writeObject(a);oos.writeObject(s);//关闭oos.close();}
}
反序列化:
public class TestObject2 {public static void main(String[] args) throws IOException, ClassNotFoundException {FileInputStream fis = new FileInputStream("d:\\info.txt");ObjectInputStream ois = new ObjectInputStream(fis);int o1 = (Integer)ois.readObject();String a = ois.readObject().toString();Object o = ois.readObject();System.out.println(o1);System.out.println(a);if( o instanceof Student) {Student s = (Student)o; // ClassCastExceptionSystem.out.println(s.getSname());} }
}
Properties
用于处理配置文件: 数据库连接,国际化文件,框架文件…
Properties位于java.util 继承Hashtable ,存储: 键值对操作,Properties高效操作键值对形式的配置文件
构造方法:
new Properties();
方法:
方法名 | 含义 | 返回值 |
---|---|---|
load(InputStream i) | 载入文件 | |
getProperty(String key) | 根据key获得值 |
public class TestProperties {public static void main(String[] args) throws IOException {Properties p = new Properties();FileInputStream fis = new FileInputStream("d:\\info.ini");//载入文件p.load(fis);//根据key获取配置文件中值System.out.println(p.getProperty("address"));System.out.println(p.getProperty("tel"));System.out.println(p.getProperty("ip"));}
}
第十二章 多线程
线程的基本概念
应用程序: 静止的程序(比如浏览器,QQ,迅雷) QQ
进程: 当应用程序启动,开辟进程,开辟独立运行的空间。 QQ.exe
线程: 程序控制流。 QQ多窗口
一个应用程序包含至少一个进程,一个进程包含多个线程。(QQ : 空间(照片,发表说说) , 聊天(多个美女唠嗑) , 游戏(农场,牧场)…)
进程和线程的区别:
- 进程是程序运行的基本单元, 必须开辟独立的内存,分配资源
- 线程是进程中一个最小的执行单元,不需要开辟独立空间
多线程的好处:提高执行效率
多线程的创建
方式1:继承类:java.lang.Thread
构造方法:
new Thread();
new Thread(String name);//传入线程名
new Thread(Runnable r);//构建线程(Runnable的实现类),多态
属性:(优先级:1-10 1最低 10最高 5默认)
MIN_PRIORITY = 1;
NORM_PRIORITY = 5;
MAX_PRIORITY = 10;
注意:优先级会影响线程执行顺序,但是并不绝对。
方法:
方法名 | 含义 | 返回值 |
---|---|---|
run() | 线程体,线程执行内容,所有子类覆盖该方法,run()不需要手动调用,启动后cpu自动调用 | void |
start() | 线程的启动,自定义的线程都需要调用该方法启动,线程启动后进入就绪状态,每个线程只启动一次 | |
getName() | 获得线程名 | String |
setName(String name) | 设置线程名 | |
currentThread() | 返回当前线程 | Thread |
setPriority(int) | 设置优先级 | |
sleep(毫秒) | 线程休眠xx毫秒 | void |
总结:
sleep() 线程自己休眠,休眠期间让出cpu给任何优先级线程,休眠结束进入就绪等待调度
join() 线程加入之后,阻塞状态,先执行该线程,启动会再join()
yieid() 线程暂停,只让出cpu给优先级高,没有比他高,继续抢占CPU
wait() Object中方法,线程等待。需要唤醒线程
方式2:实现接口:java.lang.Runnable
在企业开发中,第二种方式更为常用,实现的同时,可以有其他父类。
定义类实现接口:
public class Ticket implements Runnable{private int tickets = 10;@Overridepublic void run() {while (true) {if (tickets <= 0) {System.out.println("票卖光啦...");break;} else {tickets--;System.out.println(Thread.currentThread().getName() + "成功卖出票,剩余" + tickets + "张票");}} }
}public class TestTicket2 {public static void main(String[] args) {//Ticket是Runnable的实现类Ticket t = new Ticket(); Thread tt = new Thread(t);//多态tt.setName("窗口1");tt.start();}
}
匿名类实现多线程:
public class TestTicket3 {public static void main(String[] args) {//匿名类方式创建线程Thread t = new Thread(new Runnable() {private int tickets = 10;@Overridepublic void run() {while (true) {if (tickets <= 0) {System.out.println("票卖光啦...");break;} else {tickets--;System.out.println(Thread.currentThread().getName() + "成功卖出票,剩余" + tickets + "张票");}}}});t.start();}
}
lambda方式实现: () -> {}
Thread t = (new Thread(()->{int tickets = 10;while (true) {if (tickets <= 0) {System.out.println("票卖光啦...");break;} else {tickets--;System.out.println(Thread.currentThread().getName() + "成功卖出票,剩余" + tickets + "张票");}} },"窗口"));
线程的状态
线程开始状态 , 线程就绪状态,线程执行状态 , 线程阻塞状态 , 线程结束状态
线程的不同步
线程同步:当两个线程访问共享资源,当A线程进行访问共享资源时,B线程不能操作共享数据,线程安全的,效率低。
API 中 线程同步的接口或类:
Vector
StringBuffer
Hashtable
线程不同步:多个线程并发使用,避免使用共享数据,或者设计线程添加锁。
API 中 线程同步的接口或类:
ArrayList
StringBuilder
HashMap
JAVA中线程锁有几种形式
1.synchronized 锁(简单)
1.同步方法 给方法加锁
2.同步块 需要占用的资源放入同步块
synchronized(共享资源){对共享数据资源操作的代码;
}
同步案例:
public class BankCard { private double balance;public BankCard() {}public BankCard(double balance) {super();this.balance = balance;}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}
}public class Bank {public static void main(String[] args) {BankCard card = new BankCard(2000);/*** 创建个线程: 存钱: 5次 1000 每间隔1秒存入1000 打印余额*/Thread t1 = new Thread(new Runnable() { @Overridepublic void run() {synchronized (card) {for (int i = 1; i <= 5; i++) {card.setBalance(card.getBalance() + 1000);System.out.println(Thread.currentThread().getName() + "存入1000");System.out.println("卡内余额: " + card.getBalance());try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}},"波波");/*** 创建个线程: 取钱 :5次 取钱 判断 每1000 打印余额*/Thread t2 = new Thread(new Runnable() { @Overridepublic void run() {synchronized (card) {for (int i = 1; i <= 5; i++) {card.setBalance(card.getBalance() - 1000);System.out.println(Thread.currentThread().getName() + "取走1000");System.out.println("卡内余额: " + card.getBalance());try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}},"侯侯");t1.start();t2.start();}
}
2.Lock 锁
jdk5+新增,语法明显,更加灵活,功能强大。
lock(); //加锁
unlock();释放锁
特点: 灵活,手动随时添加和释放锁,synchronized必须等同步块运行结束,才会释放。
死锁
A线程拿到共享资源1,不释放,B线程拿到共享资源2,不释放,A和B都需要共享资源1和2才能保证运行,此时僵局就是死锁。
死锁案例;
public class MyLock {public static Object o1 = new Object();public static Object o2 = new Object();
}
public class Boy implements Runnable{@Overridepublic void run() {synchronized (MyLock.o1) {System.out.println("男孩拿到了A资源");synchronized (MyLock.o2) {System.out.println("男孩拿到了B资源");System.out.println("男孩吃到东西了");}} }
}
public class Girl implements Runnable{@Overridepublic void run() { synchronized (MyLock.o2) {System.out.println("女孩拿到了B资源");synchronized (MyLock.o1) {System.out.println("女孩拿到了A资源");System.out.println("女孩吃到东西了");}} }
}
public class TestLock {public static void main(String[] args) {Thread t1 = new Thread(new Boy());Thread t2 = new Thread(new Girl());t1.start();t2.start();}
}
线程通讯
什么是线程通讯?
多线程之间互相发送信号,线程通讯,达到多线程最高利用率,多线程高效协同工作。
线程通讯方法:
java.lang.Object中
wait(); //线程等待,进入非运行状态,等待唤醒
notify() ;//唤醒
notifyAll();唤醒所有
生产者消费模式
仓库:
package com.qf.api;
/*** 仓库* @author 86136**/
public class Clerk {//产品private int product ;/*** 生产产品(入库)*/public synchronized void produce() {if(product >= 20) {//线程等待try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else {product ++;System.out.println(Thread.currentThread().getName() + "生产产品,剩余" + product + "个产品");//唤醒notify();}}/*** 消耗产品(出库)*/public synchronized void consume() {if(product <= 0) {//线程等待try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else {product --;System.out.println(Thread.currentThread().getName() + "消耗了产品,剩余" + product + "个产品");//唤醒notify();}}
}
生产者:
package com.qf.api;
/*** 生产者线程* @author 86136**/
public class Producer implements Runnable{public Clerk c;public Producer() {} public Producer(Clerk c) {super();this.c = c;}@Overridepublic void run() {while(true) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}c.produce();} }
}
消费者:
package com.qf.api;
/*** 生产者线程* @author 86136**/
public class Consumer implements Runnable{public Clerk c; public Consumer() {} public Consumer(Clerk c) {super();this.c = c;}@Overridepublic void run() {while(true) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}c.consume();} }
}
线程池
线程池存在的意义
每个任务都需要开辟新的线程,每次消耗比较大,避免每次都开辟对象,提高线程使用效率,线程池,先初始化n个线程对象,任务之间可以由线程池调度分配线程。
线程池使用的API
顶层接口: java.util.concurrent.Executor
实现类: ExecutorService (线程池服务管理:线程接收任务 submit() 关闭线程池 shutdown() …)
帮助类 : Executors (初始化线程池)
四种形式线程池:
- 单一模式 newSingleThreadExecutor()
- 固定可重用 newFixedThreadPool(int
nThreads)- 缓存的 newCachedThreadPool()
- 定时的newScheduledThreadPool(int
corePoolSize)
ExecutorService 中方法:
方法名 | 含义 | 返回值 |
---|---|---|
shutdown() | 关闭线程池,不接受任务 | void |
submit(Callable c) | 提交任务 | Future |
submit(Runnable r) | 提交任务 | Future |
线程池案例:
public class TestPool1 {public static void main(String[] args) {//创建包含3个线程对象的线程池ExecutorService ser = Executors.newFixedThreadPool(3);//加入任务1ser.submit(()->{for (int i = 1; i <= 20; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}});//加入任务2ser.submit(()->{for (int i = 21; i <= 40; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}});//关闭线程池ser.shutdown();}
}
Callable类型:
Callable是JDK1.5之后新增的线程接口,用于设计有返回值的线程体;
Runnable和Callable:
- Runnable执行线程体run() , Callable执行线程体方法 call()
- Runnable没有返回值 Callable有返回值,Callable
- run()没有异常抛出 call()抛出异常
call();
Future: 未来线程池中线程计算结果
get(); //获得结果
Callable案例:
public class TestPool2 {public static void main(String[] args) {// 创建包含3个线程对象的线程池ExecutorService ser = Executors.newFixedThreadPool(3);// 加入任务1
// Callable<Integer> c = new Callable<Integer>() {//
// @Override
// public Integer call() throws Exception {// int sum = 0;
// for (int i = 1; i <= 100; i++) {// sum += i;
// }
// return sum;
// }
// };//Future 获取未来结果Future<Integer> f = ser.submit(() ->{int sum = 0;for (int i = 1; i <= 100; i++) {sum += i;}return sum;});try {//手动调用get()方法获取结果System.out.println(f.get());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ExecutionException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 关闭线程池ser.shutdown();}
}
第十三章 JDK8+
1.接口中非抽象方法
2.lambda表达式
3.函数式接口
4.方法引用
5.Stream流
6.日期
日期:
LocalDateLocalTimeLocalDateTime
方法:
now() //系统时间
System.out.println(local.getYear());
System.out.println(local.getMonthValue());
System.out.println(local.getDayOfMonth());
...
日期格式化:
String s = DateTimeFormatter.ofPattern("yyyy年MM月dd日").format(local);
System.out.println(s);
接口中新增非抽象方法:
public interface Animal {void eat();public default void sleep() {System.out.println("动物睡觉");}
}
Lambda表达式:
用于简化语法,简化匿名内部类。
语法:
函数式接口 变量名 = (参数1,参数2...) ->{ 方法体; [return xx] }
说明:
- 函数式接口: 接口中有一个抽象方法,因此Lambda适用于只有一个抽象方法
- 参数类型省略,一个参数()可以省略
- 方法里一条输出语句,省略{} , 有返回值省略{} 和return 直接结果
public interface Animal { int eat(int a,int b);
}Animal a2 = (a,b) -> a + b;
a2.eat(10,30);
public interface Animal { void eat(int a);
}Animal a3 = a -> sout(a);
a3.eat(100);
函数式接口:
Consumer<String> con = (s)-> System.out.println(s.length()); con.accept("jack008"); //System.out.println(sup.get()); Supplier<Double> sup = () -> Math.random();//方法引用Supplier<Double> sup2 = Math::random;
Stream流:
Stream流类似于集合,实现对集合或数组操作。
public class TestStream {public static void main(String[] args) {//原料(最原始的集合)List<String> list = Arrays.asList("jack","rose","","tom","","mary");//(流的操作)工序//list = list.stream().filter(s-> !s.isEmpty()).collect(Collectors.toList());//产品//list.forEach(System.out::println);long count = list.stream().filter(s-> s.isEmpty()).count();System.out.println(count);}
}
第十四章 JAVA AWT组件 (了解)
AWT:抽象窗口工具集,JAVA图形界面
SWING:图形界面
SWT:新的
java.awt 包
javax.swing包
窗口: JFrame
package com.qf.api;import java.awt.FlowLayout;
import java.text.SimpleDateFormat;
import java.util.Date;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;public class MyFrame extends JFrame{public MyFrame() { //布局 setLayout(new FlowLayout()); JButton btn = new JButton("点击试试");JTextField txt = new JTextField(20);JLabel label = new JLabel();//btn.setLocation(100, 50);//指定组件的位置//btn.setSize(80, 30);//指定组件的大小//txt.setSize(200, 30);//add(btn); Date d = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");label.setText(sdf.format(d));//创建线程(匿名类/lambda)add(label);//add(txt);this.setTitle("我的第一个窗口");this.setSize(600, 400);this.setVisible(true);}public static void main(String[] args) {new MyFrame();}
}
JAVA API (application programming interface)相关推荐
- HBase JAVA API(大章鱼版)
阅读前请注意: 此api中的环境为大章鱼大数据学习平台提供,非此环境,jar包,与程序代码存在一定问题.如果想本地虚拟机运行请参考分布式数据应用,进行操作 任务目标 1.了解HBase语言的基本语法 ...
- 容易忽视但是功能灰常强大的Java API(五. 二分查找)
五. 二分查找 二分查找是一个高效的查找算法,在java的集合对象中也提供了二分查找的算法,如下面的java api接口: java.util.Arrays.binarySearch(java.lan ...
- 安卓操作系统版本(Version)与应用程序编程接口等级(Application Programming Interface Level)对照表...
Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑. 使用Android API,可以在Java环境开发App,编译.打包后可在Android系统 ...
- 容易忽视但是功能灰常强大的Java API(二. 读写对象)
二. 读写对象 有时候你会遇到这样的情况:从数据集合中读取数据,解析数据,然后封装成对象,再把对象放到一个集合中,对集合对象进行操作,程序结束.第二次需要运行程序时,又按如上的操作流程做一遍.第三次, ...
- 【JAVA基础】重新系统学习Java(七)常用API(String、ArrayList)
目录 常用API(String.ArrayList) String String类概述 创建字符串对象的2种方式 String类常见面试题 String类常用API-字符串内容比较 String类常用 ...
- 7.Java常用API(String、ArrayList)
API(Application Programming Interface, 应用程序编程接口) Java写好的技术(功能代码),可以直接调用 1.String String类定义的变量可以用于存储字 ...
- API(Application Programming Interface,应用程序编程接口)
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码 ...
- API(Application Programming Interface)
API(Application Programming Interface) 文章目录 API(Application Programming Interface) 一.API概述 二.Object类 ...
- DAPI(Distributed Application Program Interface)
DAPI 最近在做区块链平台,发现需要定一个API接口实现对去快乐的访问,而区块链是一个分布式系统,对其的调用有两种常见方式: 构建一个独立的同步节点,和区块链保持同步,通过节点API实现区块链的访问 ...
- Java——API(接口)
目录 Java 接口 接口与类相似点: 接口与类的区别: 接口特性 抽象类和接口的区别 接口的声明 NameOfInterface.java 文件代码: 实例 Animal.java 文件代码: 接口 ...
最新文章
- java 框架 Dao层 Mapper层 controller层 service层 model层 entity层 简介
- 网站推广下吉利关联公司公开“车辆故障预测方法”将在事故发生前预警
- 【Android 逆向】ELF 文件格式 ( 程序头数据 | 节区头数据 | 动态符号表 )
- 【字节码插桩】Android 打包流程 | Android 中的字节码操作方式 | AOP 面向切面编程 | APT 编译时技术
- android 动态设置View的高度和宽度,ViewTreeObserver使用
- 深度学习--Keras总结
- 一文吃透Json解析工具类合集(FastJson、Jackson、Gson)
- 什么人不在生死簿_地府在孙悟空划掉生死簿以后,因为什么原因不组织重写?...
- 透析 | 卷积神经网络CNN究竟是怎样一步一步工作的?
- Android实例-屏幕操持常亮(XE8+小米2)
- mpacc和计算机硕士,考MPAcc还是工作?读研三年VS工作三年对比!
- 一个简单的WeakList的实现
- 360手机助手pc版 v2.4.0.1265 官方版
- 台式电脑怎么组装步骤_台式电脑组装教程图解,手把手教您组装(零基础也能搞定)...
- P2142 高精度减法
- 【随笔记】做事要讲究轻重缓急,一定要把握主次轻重。
- vue 中的 prop
- 网络安全系列之二十六 EFS加密
- div overflow属性
- linux 文件唯一标识符,详解Linux中获取全球唯一标示符UUID的方法