一、Javase基础
//快捷键
crtl+d //复制选择的行
alt+选择列 //选择同列
alt+shift+方向键 //移动整行
crtl+alt+l //格式化代码
3>>1 //0000 0011 >>1 向右移动一位为 0000 0001
<< //同理
1.1 jdk环境变量配置
|官网下载oracle.com/java
|可以下载安装版和解压版这里下载解压版
|开始配置环境变量,打开系统变量配置,变量值填写jdk解压的目录。
|点击新建CLASSPATH,填写如下
|找到path变量编辑。
|测试配置是否成功打开cmd,输入java -version
二、java基本语法
2.1 八种基本类型
关键字 字节数
|byte 1
|int 4
|short 2
|long 8
|float 4
|char 2
|boolen 1
|double 8
面试题
byte j = 1;
j = j+1;
问:这样写有错吗?
答:错误,应为j为若类型1为强类型,最终j+1为int,而j为byte。所以错误。
j+=1; //可以,会自动转换
int x = 1;
x = x++
jvm 先开辟一段变量空间1,
运算时jvm 先备份x的值1,此时变量空间为2,
最后结果备份空间的1覆盖变量空间的2。结果为1。
X++在栈内存空间中先备份在自增,++X在栈内存空间是先自增在备份
2.2 格式化
%s //字符串
%d //十进制整数
System.out.printf(%06d%n,1); //输出六位,不够在左边补零。%n 换行。 000001
%f //浮点类型
System.out.printf("%.2f%n",1); //1.00
//2022年01月05日星期三
long t = System.currentTimeMillis();
System.out.printf("%tY年%<tm月%<td日%<tA", t);
//SimpleDateFormat
yyyy:年
MM:月
dd:日
hh:1~12小时制(1-12)
HH:24小时制(0-23)
mm:分
ss:秒
S:毫秒
E:星期几
D:一年中的第几天
F:一月中的第几个星期(会把这个月总共过的天数除以7)
w:一年中的第几个星期
W:一月中的第几星期(会根据实际情况来算)
a:上下午标识
k:和HH差不多,表示一天24小时制(1-24)。
K:和hh差不多,表示一天12小时制(0-11)。
z:表示时区
//Calendar
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR,1999);
c.set(Calendar.MONTH,-5);
c.set(Calendar.DATE,2);
System.out.printf("%tF%n",c);
//输出为1998-08-02
//系统时间戳,是一个long整数
long time = System.currentTimeMillis();
System.out.println(time);
//七天前的日期
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, -7);
System.out.printf("%tF %<tT %<tA",c);
//2021-12-30 15:29:30 星期四
//当前月的最后一天
Calendar c = Calendar.getInstance(); c.set(Calendar.MONTH,c.get(Calendar.MONTH)+1);
c.set(Calendar.DAY_OF_MONTH,0);
System.out.printf("%tF %<tT %<tA",c);
//2022-01-31 15:39:29 星期一
//格式化数字
NumberFormat n = NumberFormat.getPercentInstance();
System.out.println(n.format(0.1));
//输出10%
Math
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zyXbrfaW-1645837761037)(C:\Users\Jsm\AppData\Roaming\Typora\typora-user-images\image-20220106202550150.png)]
判断生肖
Calendar c =Calendar.getInstance();
// c.set(Calendar.YEAR,2004);
int y = c.get(Calendar.YEAR);
System.out.println(" 鼠牛虎兔龙蛇马羊猴鸡狗猪".charAt((y%12)-3));
}}
2.3 随机数
//uuid全球唯一
UUID id = UUID.randomUUID();
System.out.println(id);
System.out.println(id.toString().length());
//bf256606-f221-480d-9a30-414b9a25b1eb
36
//随即类Random
Random id = new Random();
System.out.println(id.nextBoolean());
System.out.println(id.nextInt(8));
double l = Math.random();
System.out.println(l);
System.out.println(id.nextFloat());
System.out.println(id.nextLong());
System.out.println(id.nextGaussian());
//true
7 //0-7的随机数
0.5802719553791326 //返回double型
0.41117424 //返回浮点型
2406792565195574480 //返回长整型
2.7469001365076404 //返回伪随机高斯双精度值。
2.4 循环语句
//swith 支持的数据类型
基本数据类型:byte, short, char, int
包装数据类型:Byte, Short, Character, Integer
枚举类型:Enum
字符串类型:String(Jdk 7+ 开始支持)
百钱百鸡
public class java22 {
public static void main(String[] args) {
for (int i = 0; i <= 20; i++) {
for (int j = 0; j <= 33; j++) {
if( i * 5 + j *3 +(100 - i - j)/3 == 100 && (100 - i - j) % 3 == 0){
System.out.printf("%d %d %d%n",i, j, 100-i - j );
}
}
}
}
}
猜数字
Random rand = new Random();
Scanner sc = new Scanner(System.in);
int nums = rand.nextInt(100) + 1;
int n = 0;
while (true){
++n;
int temp = 0;
System.out.print("请输入数字[1-100]:");
if(sc.hashNextInt()){
temp = sc.nextInt();
}else{
String s = sc.next();
if("quit".contain(s)){
sc.close();
System.out.printf("程序退出,游戏结束!%n");
break;
}
System.out.printf("输入有误%s,请重新输入!%n",s);
continue;
}
if(temp > num ){
System.out.printf("%d、太小了%n",n);
}else if(temp < num){
System.out.printf("%d、太大了",n);
}else {
if(n == 1){
System.out.printf("厉害啊,你的成绩为%d分",100);
}else{
System.out.printf("%d、恭喜,你的成绩为:d%分",n,110-n*10);
}
break;
}
三、数组
3.1 遍历操作
int[] a = new int[]{1,2,3,4};
System.out.println(a.length); //4
System.out.println(a[2]); //3
//遍历1
for (int i : a ){
System.out.println(a.length);
}
//遍历2
for(int i = 0; i < a.length; i++){
System.out.println(a[i]);
}
//遍历3
for(int i = a.length; i >=0; i++){
System.out.println(a[i]);
}
//遍历4
Arrays.strtam(a).forEach(System.out::println);
//声明一个数组,初始化10个1-100随机数
Random r = new Random();
Integer[] n = new Integer[10];
for(int i = 0; i< n.length; i++){
n[i] = r.nextInt(100) + 1;
}
//排序前遍历输出
for(Integer e : n){
System.out.printf("%d", e);
}
System.out.println();
//降序
Arrays.sort(n, (a, b) -> b - a);
//乱序
Arrays.sort(nums,(a, b ) -> rand.nextBolean ? 1:-1)
//排序后遍历输出
for(Integer e : n){
System.out.printf("%d", e);
}
System.out.println();
Random r = new Random();
int[] nums = new int[10];
for(int i = 0; i < nums.length; i++){
nums[i] = r.nextInt(100) + 1;
}
//冒泡
for (int i = 0; i < nums.length - 1; i++){
for(int j = 0; j < nums.length - 1 -i; j++){
//>升序 <降序
if(nums[j] < nums[j + 1]){
int t = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = t;
}
}
}
System.out.printf("排序后%s%n",Arrays.toString(nums));
3.2 排序查找
public class Arr {
public static void main(String[] args) {
int[] a = {1,2,43,4,5};
//检查有没有43
boolean f = false;
for(int i : a){
if(i == 43){
f = true;
break;
}
}
if (f){
System.out.println("有");
}else{
System.out.println("无");
}
Arrays.sort(a);
int c = Arrays.binarySearch(a, 43); //二分查找
if(c < 0 ){
System.out.println("没有");
}else{
System.out.println("有["+c+"]");
}
System.out.print(c);
//遍历二位数组
int[][] n = new int[3][6];
System.out.println(n.length);
System.out.println(Arrays.deepToString(n));
for(int[] i : n){
for(int j : i ){
System.out.printf("%d",j);}
}
System.out.println();
}
}
四、面向对象OOP
面试题
float/double //默认输出为0.0
String //默认为null
int //默认为0
boolean //默认flase
4.1 类class
//类
|共同方法和属性的集合就是类
|张三和人类的关系 张三对象 人类是类
人类 zs = new 人类();
4.2 定义类
public //全局 类的修饰符
abstract //抽象
final //最终
class //类
extend //继承
implement //实现
4.3 静态变量(类变量)
|静态变量只分配一次内存,不需要实例化,如果实例化则会覆盖原来的值。最终所有的对象都指向同一个值(内存地址)。一般计数用静态变量。
面试题
//计算1+2+3+...100=?不能用循环和递归
//使用java8 instream流技术
int s = InStream.rangeClosed(1,100).sum();
System.out.println(s);
4.4 递归
//阶乘
static int jiecheng(int n ){
if(n == 1){
return 1;
}else{
return n * jiecheng(n - 1);
}
}
//斐波那契数列
public class OOP {
public static void main(String[] args) {
for (int i = 0; i <=6; i++) {
System.out.printf(fib(i) + " ");
}
}
static int fib(int n){
if((n == 0) || (n == 1)){
return 1;
}else {
return fib(n - 1) + fib(n - 2);
}
}
}
4.5 静态代码程序段
public class OOP1 {
//静态程序段,第一次实例化自动执行
static {
System.out.println("p1");
}
//初始化程序段,每次都会执行
{
System.out.println("p2");
}
{
System.out.println("p3");
}
static {
System.out.println("p4");
}
//在实例化时自动执行,无需返回值。
public OOP1(){
System.out.println("无参构造");
}
public OOP1(int n){
System.out.println("有参构造");
}
public static void main(String[] args) {
OOP1 j = new OOP1();
}
}
结果:
p1
p4
p2
p3
无参构造
//GenerateAllSetter插件可以自动生产getter setter方法快捷键alt+回车键
4.6 继承
总结:在不同包下面能够访问的权限修饰符只有: pulbic 与protected,但是 protected 必须要有继承的关系才能够访问。
this.id //使用本类中的属性
super.id //使用父类中的属性
如果本类没有声明这个属性则默认调用父类的属性。
4.7 UML
|实线空心箭头代表继承
|虚线空心箭头代表实现
//idea plantuml 网站参考 https://plantuml.com/zh/
4.8 重载和重写
方法重写规则:
重写方法名和参数(个数、类型)必须和被重写的方法相同重写方法的返回类型必须和被重写方法相同方法的申明权限不能比被重写方法低,如父类是public,就不能是protectedfinal的方法不能被重写,static的方法不能被重写,但能被再次申明父类和子类在同一个包,子类能重写父类所有方法,除了final和private方法父类和子类不在同一个包,子类只能重写父类public和protected的非final方法子类可以抛出非强制异常(RunTimeException),不能抛出新的强制异常或比父类更泛的强制异常,如父类抛出IoException,子类不能抛出Exception,但可以抛出ioexceprion的子异常父类的构造方法不能被重写
方法重载规则:
被重载方法必须修改(参数类型或个数);重载方法返回类型可以改变;重载方法的修饰符可以改变;重载方法可以抛出新的异常或更广的异常;方法只能在同一个类或子类中被重载
OverRide和OverLoad区别
区别 OverRide OverLoad 参数 (个数或类型) 不能修改 必须修改 返回类型 不能修改 可以修改 访问申明 可以申明更严限制(父类public子类不能申明protected) 可以修改 异常不能抛出新强制异常或更高级的强制异常,可以抛出子异常。
4.9 抽象类
//java语言中,抽象方法是说没有方法的实现(方法体)此方法为抽象方法,只有抽象类和接口中才可以有抽象方法。
public abstract int pf(int i); //抽象方法
使用规则
1. 抽象类必须被继承,抽象方法必须被重写。
2. 抽象类中的抽象方法只需声明,无需实现,没有方法体;
3. 抽象类不能被实例化,抽象类不一定要包含抽象方法,而定义抽象方法的类必须是抽象类。
4. 抽象类包含的抽象方法必须在其子类中被实现,否则该子类也必须是抽象类。
5. 抽象类可以有构造方法供子类实例化对象
6. 抽象类不能直接实例化使用,一般用的是抽象类的子类,
A a = new B();
A和B之间的关系,继承关系,接口实例关系。
类:方法+属性+静态程序段+初始化程序段
抽象类:方法+属性+静态程序段+初始化程序段+抽象方法
抽象类本质
1.从类的组成上看其是抽象方法和非抽象方法的集合,还有属性(常量)。
2.从设计的角度来看,实际上抽象类定义了一套规范(抽象方法)。(规范)
规范:抽象类(相当于规范,约束程序员不会乱写代码)和接口
例如数据库连接,由于连接的方式不同故将连接方式规范一下设置成抽象方法。统一的方法直接子类调用,不能统一的就设置成抽象方法。
4.10 接口
|接口是静态常量和抽象方法的集合
|接口中抽象方法,没有使用abstract 没有public 也是public
|接口可以继承多个接口
函数式接口:如果一个接口中,有且只有一个抽象方法,此接口默认是函数接口
可以使用在接口声明处,添加 @FunctionalInterface 注解来说明是函数式接口
函数式接口,可以使用lambda 表达式来编写,代码精简,必须出现内部类
java 1.8 增加了3个功能(1) 函数接口 (2) default默认实现方法 (3) static静态实现*/
//静态实现方法,直接使用接口,直接调用
抽象类和接口的区别
abstract class Db{}
特点:是一个类,可有抽象方法,也可以有实现方法,如果有抽象方法,则必须为抽象类,使用它的子类,如果子类没有实现所有抽象方法,那子类也必须为抽象类。
interface Db{}
特点:全局常量,全局抽象方法,全局static 静态实现方法,全局default默认实现方法。`java1.8对接口已经可以有直接实现的方法功用,还有如果一个接口只有一个抽象方法,必须自动为函数式接口`
企业框架开发中,使用接口比较多。比如:java体系内部JDBC全是接口
jdbc Connection 是个类是个接口
一般写抽象类和接口是什么人?管理人员、架构师,mybatis interface
java api api “10”
4.11 装箱、拆箱
基本类型 | 包装器类型(对象类型) valueOf() .parse() |
---|---|
boolean | Boolean |
char | Character |
int | Integer |
byte | Byte |
short | Short |
long | Long |
float | Float |
double | Double |
4.12 内部类
内部类可以用修饰符修饰叫成员内部类
内部类的共性内部类分为: 成员内部类、静态嵌套类、匿名内部类(直接实例化抽象类或者直接实例化接口)。
(1)、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
(2)、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。
(3)、外部类不能直接访问其内部类,想要访问内部类,需实例化内部类
(4)、内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量。
(5)、其他类想要直接访问内部类,可直接实例化内部类,方法如下外部类名.内部类 对象名 = new 外部类().new 内部类();
例:Out.In in = new Out().new In();
如果内部类是静态的,当其他类调用内部类可直接通过类名调用,格式如下:
外部类.内部类 对象名 = new 外部类.内部类()
例:Out.In in2 = new Out.In();
当内部类是静态的,且方法也是静态的,此时可不需实例化对象
外部类.内部类.静态方法名();
例:Out.In.fun();
System.out.print();
面试题
父子类中静态方法、构造代码块、构造方法的执行顺序为 :父类静态方法>子类静态方法父>父类构造代码块>父类构造方法>子类构造代码块>子类构造方法。
五、字符串、正则表达式
equalsIgnoreCase() //方法用于将字符串与指定的对象比较,不考虑大小写。
toCharArray() //方法将字符串转换为字符数组
charAt //数字转化为字符
toLowerCase() // 方法将字符串转换为小写。
repeat() //方法返回一个新字符串,表示将原字符串重复n次。
matches() // 方法用于检测字符串是否匹配给定的正则表达式。
5.1 转义字符和所对应的意义
所有的转义字符和所对应的意义:
转义字符 | 意义 | ASCII码值(十进制) |
---|---|---|
\b | 退格(BS) ,将当前位置移到前一列 | 008 |
\f | 换页(FF),将当前位置移到下页开头 | 012 |
\n | 换行(LF) ,将当前位置移到下一行开头 | 010 |
\r | 回车(CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表(HT) (跳到下一个TAB位置) | 009 |
\v | 垂直制表(VT) | 011 |
\ | 代表一个反斜线字符’’' | 092 |
’ | 代表一个单引号(撇号)字符 | 039 |
" | 代表一个双引号字符 | 034 |
\0 | 空字符(NULL) | 000 |
\ddd | 1到3位八进制数所代表的任意字符 | 三位八进制 |
\uhhhh | 1到2位十六进制所代表的任意字符 | 二位十六进制 |
Arrays 工具类的使用
Arrays.toString(数组) //输出数组信息
Arrays.equals(,) //比较两个数组是否形同
Arrays.fill(arr,10) //将指定的值填充到数组中
Arrays.sort(arr) //将数组排序
Arrays.binarySearch(arr,10) //二分查找返回值的索引
String
String
声明finally,不能被继承
实现了serializable接口,表示字符串支持序列化的
实现了comparable接口,表示String可以比较大小
内部定义了char[] 数组,
String代表不变的字符序列,不可变性
变量在堆里面,insert()方法返回值在常量池中。
最长公共子串,每一轮掐掉一个然后错位比较。
String常用方法
length() //数组长度
isEmpty() //==null和length是否为0,
isbank() //是否由空格组成
charAt() //返回下标的内容
tolowerCase() //忽略小写
toUpperCase() //忽略大写
compareTo() //比较两个字符串的ask码是返回差值。
substring() //从数组下标的位置截取,左闭右开
endWith("str") //是否由指定字符串结尾的
startWith("str") //指定的字符开始的
startWith("str",index) //是否是从index索引开始以str
str1.contains(str2) //是否包含str2
indexOf("str") //首次出现的位置返回int索引
indexOf("str",index) //指定字符串从索引index处开始找
lastIndexOf() //指定字符串最后一次出现的位置,返回索引
lastIndexOf("str",index) //指定index处反向搜索
lastIndexOf和IndexOf在str唯一的情况下和为空的情况下返回一样
replace(oldstr,newstr) //替换
replaceAll(regex,str) //regex正则,
match(regex) //匹配正则表达式返回bollean
split(regex) //切割返回一个字符数组
String 与基本数据类型的转换包装类
Integer.parseInt(str) //返回int
String.valueOf(int) //返回String
String与charArry[]转换
toCharArray //转换为char数组
String与byte[]转换
str.getbyte() //也可以指定字符集编码
Array.toString(str.getbyte()) //输出
new String(byte) //解码
面试题
String s = new String();
创建了几个对象
两个,一个是堆中存放的,另一个是char[] 在常量池中
面试题
String j = "ok";
String j1 = "ok";
String j2 = new String("ok");
String j3 = "Ok";
// == 是判断是不是一个对象
System.out.println(j==j1);
System.out.println(j==j2);
System.out.println(j==j3);
//判断字符串值是不是一样的
System.out.println(j.equals(j2));
System.out.println(j.equalsIgnoreCase(j3));
System.out.println(j.length());
System.out.println("中国China".length());
System.out.println("中国China".getBytes().length);
//判断字符串变量和一个字符串变量是不是一样
String name = "jsm";
String name = null;
System.out.println(name.equalsIgnoreCase("jsm"));
//优于上面一行,避免空指针异常
System.out.println("jsm".equalsIgnoreCase(name));
//结果
true
false
false
true
true
2字符
7字符
11字节
true
true
1. 将一个字符串数组进行分组输出,每组中的字符串都由相同的字符组成。
举个例子:输入[“eat”,”tea”,”tan”,”ate”,”nat”,”bat”]
输出[[“ate”,”eat”,”tea”],[“nat”,”tan”],[“bat”]]
5.2字符串的截取
package cn.webrx;
public class Str3 {
public static void main(String[] args) {
var s = "ok";
String s2 = new String("ok");
System.out.println(s == s2);//false
System.out.println(s.equals(s2));//true
System.out.println("Java".equalsIgnoreCase("JAVA"));//true
var ss = "中国河南郑州";
System.out.println(ss.length());//字数
System.out.println(ss.substring(0));
System.out.println(ss.substring(0,2));
System.out.println(ss.substring(2,4));
System.out.println(ss.charAt(2));//河
int w = 1;
System.out.println("星期" + "日一二三四五六".charAt(w));
//判断
System.out.println("javascript2021".startsWith("java"));//true
System.out.println("javascript2021".endsWith("21"));//true
System.out.println("javascript2021".contains("java"));//true
System.out.println("java".indexOf("a"));//1
System.out.println("java".lastIndexOf("a"));//3
System.out.println("java".lastIndexOf("p"));//-1
//字符串替换
System.out.println("java".replace('a', 'b'));
//
System.out.println("1234java2021".replaceAll("\\d+",""));
}
}
// 判断字符串是否为空白
" ".isBlank(); // true
// 去除首尾空格
" Javastack ".strip(); // "Javastack"
// 去除尾部空格
" Javastack ".stripTrailing(); // " Javastack"
// 去除首部空格
" Javastack ".stripLeading(); // "Javastack "
// 复制字符串
"Java".repeat(3); // "JavaJavaJava"
// 行数统计
"A\nB\nC".lines().count(); // 3
String str = "Java";
// 小于0:java.lang.IllegalArgumentException
System.out.println(str.repeat(-2));
// 等于0:空白串("")
System.out.println(str.repeat(0));
// JavaJavaJava
System.out.println(str.repeat(3));
// java.lang.OutOfMemoryError
System.out.println(str.repeat(Integer.MAX_VALUE));
// 4
System.out.println("A\nB\nC\rD".lines().count());
5.3 StringBulider和StringBuffer
它们都是可变字符串,使用上功能上基本一样,StringBuilder不支持多线程(非线程安全),它们都支持动态修改。
序号 | 方法描述 |
---|---|
1 | public StringBuffer append(String s) 将指定的字符串追加到此字符序列。 |
2 | public StringBuffer reverse() 将此字符序列用其反转形式取代。 |
3 | public delete(int start, int end) 移除此序列的子字符串中的字符。 |
4 | public insert(int offset, int i) 将 int 参数的字符串表示形式插入此序列中。 |
5 | insert(int offset, String str) 将 str 参数的字符串插入此序列中。 |
6 | replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。 |
1 | int capacity() 返回当前容量。 |
---|---|
2 | char charAt(int index) 返回此序列中指定索引处的 char 值。 |
3 | void ensureCapacity(int minimumCapacity) 确保容量至少等于指定的最小值。 |
4 | void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将字符从此序列复制到目标字符数组 dst 。 |
5 | int indexOf(String str) 返回第一次出现的指定子字符串在该字符串中的索引。 |
6 | int indexOf(String str, int fromIndex) 从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。 |
7 | int lastIndexOf(String str) 返回最右边出现的指定子字符串在此字符串中的索引。 |
8 | int lastIndexOf(String str, int fromIndex) 返回 String 对象中子字符串最后出现的位置。 |
9 | int length() 返回长度(字符数)。 |
10 | void setCharAt(int index, char ch) 将给定索引处的字符设置为 ch 。 |
11 | void setLength(int newLength) 设置字符序列的长度。 |
12 | CharSequence subSequence(int start, int end) 返回一个新的字符序列,该字符序列是此序列的子序列。 |
13 | String substring(int start) 返回一个新的 String ,它包含此字符序列当前所包含的字符子序列。 |
14 | String substring(int start, int end) 返回一个新的 String ,它包含此序列当前所包含的字符子序列。 |
15 | String toString() 返回此序列中数据的字符串表示形式。 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZhAB7Nc-1645837761039)(https://gitee.com/webrx/wx_note/raw/master/images/2021-03-01-java-stringbuffer.svg)]
面试题
- 描述StringBulider和StringBuffer的区别
string 固定不可变字符串 | StringBuffer 可变 | StringBuilder |
---|---|---|
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间 | StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 | 可变类,速度更快 |
不可变 | 可变 | 可变 |
线程安全 | 线程不安全 | |
多线程操作字符串 | 单线程操作字符串 |
5.4 正则表达式
Pattern **类:**pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher **类:**Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
- 正则表达式基本语法规则
字符 | 说明 | 实例 |
---|---|---|
^ | 表达式开始 | |
$ | 表达式结尾 | |
[3,5,8,a-z] | 一个符号,符号范围在3,5,8,a-z | |
\d === [0-9] | 代表一位数字 | |
\d+ | 代表1个数字,或多个数字 | |
\d{3} | 代表3个数字 | |
[\u4e00-\u9fa5]{2,8} | 代表2到8个汉字字符 | |
* | 代表0个或多个前边的符号 | [a-z]* |
. | 代表1个任意的符号 | str.matches("^.+$") |
+ | 代表1个或多个前边的符号 | \\d+ |
? | 代表0个或1个前边的符号 {0,1} | |
{n} | n个 | |
{n,} | n个或多个 | |
{m,n} | ||
\D | [^0-9] | |
\w | [a-zA-Z0-9_] | |
\W | [^a-zA-Z0-9_] | |
(|) | 匹配或正则表达式或,分组功能 | |
() | 分组 |
- 正则贪婪械,禁用贪婪
public class Reg9 {
public static void main(String[] args) {
String a = "java8php123javascript6mysql88888html5";
System.out.println(a);
System.out.println(a.replaceAll("\\d+?", "-"));//?禁用贪婪
String str = """
<div>hello</div><div>java 15</div><div><p>java 15</p><span>java 8</p><div>java 15</div></div>
""";
Pattern p = Pattern.compile("<div>.*?java.*?</div>");
Matcher m = p.matcher(str);
while(m.find()) {
System.out.println(m.group());
}
}
}
String h = "<div>hello</div><span>java</span><div>java</div>";
//打印输出<div></div>标签中的内容
//hello
//java
// 此处?是禁用贪婪模式
var pattern = Pattern.compile("<div>(.*?)</div>");
var m = pattern.matcher(h);
while (m.find()) {
System.out.println(m.group(1));
}
- 正则表达式分组
public class Reg10 {
public static void main(String[] args) {
String a = "java8php123javascript6mysql88888html5";
//System.out.println(a);
//System.out.println(a.replaceAll("\\d+?", "-"));//?禁用贪婪
String str = """
<div>hello</div><div>java 15</div><div><p>java 15</p><span>java 8</p><div>java 13</div><div>java 162423423</div>
""";
System.out.println(str.replaceAll("<[a-z]+>|</[a-z]+>", ""));
System.exit(0);
Pattern p = Pattern.compile("(<div>java )(\\d+)(</div>)");
//System.out.println(str.replaceAll(p.pattern(), "$18$3"));
System.out.println(str.replaceAll("<(div)(>java \\d+</)(div)>", "<h3$2h3>"));
Matcher m = p.matcher(str);
while(m.find()) {
System.out.println(m.group().replaceAll("<div>(.*)</div>", "$1"));
}
//<div>java 数字</div> 修改为 <div>java 8</div>
}
}
/*
* Copyright (c) 2006, 2021, webrx.cn All rights reserved.
*
*/
package cn.webrx;
import java.util.regex.Pattern;
/**
* <p>Project: javase - Reg9
* <p>Powered by webrx On 2021-12-07 15:31:14
* <p>Created by IntelliJ IDEA
*
* @author webrx [webrx@126.com]
* @version 1.0
* @since 17
*/
public class Reg9 {
public static void main(String[] args) {
//显示div标签有java的标签直接显示
String h = "java<div>hello-java</div><br><div>htm</div><span>java</span><div>java</div>java<div>hellojavascriptok</div>";
var p = Pattern.compile("<div>[\\-a-z\\s]*?java[\\-a-z\\s]*?</div>", Pattern.MULTILINE);
var m = p.matcher(h);
while (m.find()) {
System.out.println(m.group());
}
System.out.println(h);
//div标签中包括java字符串,全部替换为javb字符串
String t = h.replaceAll("(<div>[\\-a-z\\s]*?)(java)([\\-a-z\\s]*?</div>)", "$1javb$3");
System.out.println(t);
}
}
group()
public static void main( String args[] ){
// 按指定模式在字符串查找
String line = "123ra9040 123123aj234 adf12322ad 222jsk22";
String pattern = "(\\d+)([a-z]+)(\\d+)";
// String pattern1 = "([\\u4E00-\\u9FA5]+|\\w+)";
// 创建 Pattern 对象
Pattern r = Pattern.compile(pattern);
// 现在创建 matcher 对象
Matcher m = r.matcher(line);
int i = 0;
// m.find 是否找到正则表达式中符合条件的字符串
while (m.find( )) {
// 拿到上面匹配到的数据
System.out.println("----i="+i);
System.out.println("Found value: " + m.group(0) );
System.out.println("Found value: " + m.group(1) );
System.out.println("Found value: " + m.group(2) );
System.out.println("Found value: " + m.group(3) );
i++;
System.out.println("|||||||");
System.out.println("");
}
}
输出结果
----i=0
Found value: 123ra9040
Found value: 123 group(1)坐
Found value: ra group(2)中
Found value: 9040 group(3)右
|||||||
----i=1
Found value: 123123aj234
Found value: 123123
Found value: aj
Found value: 234
|||||||
----i=2
Found value: 222jsk22
Found value: 222
Found value: jsk
Found value: 22
|||||||
总结:
Matcher
类中group(0)
表示正则表达式中符合条件的字符串。Matcher
类中group(1)
表示正则表达式中符合条件的字符串中的第一个() 中的字符串。Matcher
类中group(2)
表示正则表达式中符合条件的字符串中的第二个() 中的字符串。Matcher
类中group(3)
表示正则表达式中符合条件的字符串中的第三个() 中的字符串
六、异常处理
6.1 异常概念
异常:在程序运行过程中发生的异常事件,由外部问题导致。异常属于对象。编译时产生的异常不是。
异常一般分两类,Error与Exception。
java异常处理:try catch finally throw throws Java.lang.Exception
七、集合泛型
Collection接口中常用的方法
-
1 public boolean add(E e):添加一个元素 2 public void clear():清空集合中所有的元素 3 public boolean remove(E e):移除集合中指定的元素 4 public boolean contains(E e):检查集合中是否包含指定的对象,比的是内容不是地址。 5 public boolean isEmpty():判断集合是否为空 6 public void size():判断集合中元素的个数 7 public Object[] toArray():把集合元素存储到数组中 8 containsAll 一个集合是否包含另一个集合的全部内容 9 removeAll 相当于差集,就是把两个集合中相同的部分去掉。返回一个集合。 10 retainAll 相当于交集。 11 hashCode 返回一个哈希值 12 toArray 集合到数组的转换 13 Arrays.asList 数组到集合的转换 14 Iterator 专门为容器而生,遍历集合,相当于检票员,看看集合里面的人买没买票,就是下一个next指针下移。他的remove方法相当于把没有买票的人删除,就相当于把集合中的不想要的数据删除。
ArrayList常用方法
indexOf() //返回集合中首次出现的位置,否则返回-1
lastIndexOf //返回最后一次出现的位置。
set //设置值
sublist //左闭右开的范围,
get //得到值
Set常用方法
无序不可重复,不等于随机性
linkedHashSet 有序,遍历时可以按照添加的顺序。
Treeset 同一个对象添加数据。遍历出来的有序
没有额外定义新的方法。
如果是对象添加数据则需要重写hashcode(先)方法和equals方法。
Map常用方法
学生和分数。k,v。
set承装k。collection承装v。使用set存储所有的entry<k,v>,就是map。
加载因子为0.75,临界值为12,超过12开始扩容2倍。树化最小值16.
collections 工具类
reverse(list) //反转数据
copy(des,src) //如果des的长度小于sec会抛出异常List des = Arrays.asList(new Object[src.size()]);
frequency(list,list.get(0)) //在list集合中第一个元素出现了几次
shuffle(list) //洗牌
sort(list) //排序
swap(list,1,2) //交换值
List list = Collectio ns.synchronizedList(list1); //使ArrayList线程安全。
-
Collection为集合层级的根接口。一个集合代表一组对象,这些对象即为它的元素。Java平台不提供这个接口任何直接的实现。
-
Set是一个不能包含重复元素的集合。这个接口对数学集合抽象进行建模,被用来代表集合,就如一副牌。
(1)不允许存储重复的元素
(2)没有索引,不能使用普通的for循环遍历 -
List是一个有序集合,可以包含重复元素。你可以通过它的索引来访问任何元素。List更像长度动态变换的数组。
(1)有序的集合,即存储和取出元素的顺序相同
(2)允许存储重复的元素
(3)有索引,可以使用普通的for循环遍历 -
Map是一个将key映射到value的对象.一个Map不能包含重复的key:每个key最多只能映射一个value。k,v可以为null 线程不安全。TreeMap根据k排序
-
一些其它的接口有Queue、Dequeue、SortedSet、SortedMap和ListIterator。
7.1 Collection List
- Collection接口-》List接口-》ArrayList是List的实现类
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("javascript");
list.add(0,"java"); //指定位置添加
list.addAll(1,List.of("php","python","java")); //添加多个
System.out.println(list);
// list.remove("php"); //移除元素
// list.remove(1); //移除索引为1的元素
//list.clear(); //清空
System.out.println(list.contains("java")); //是否包含
// System.out.println(list.containsAll(List.of("java","php"))); //是否包含多个对象
System.out.println(list.indexOf("java")); //第一次出现的索引位置
System.out.println(list.lastIndexOf("java")); //最后一次索引出现的位置
System.out.println(list);
System.out.println(list.size()); //集合长度
//结果
[java, php, python, java, javascript]
true
0
3
[java, php, python, java, javascript]
5
- 遍历:
//迭代器遍历
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()){
String s = listIterator.next();
System.out.println(s);
}
// 遍历1
for (int i = 0; i < list.size(); i++) {
String l = list.get(i);
System.out.println(l);
}
//遍历2
for(String j : list){
System.out.println(j);
}
//遍历3
list.forEach(System.out::println);
-
排序
public static void main(String[] args) { List<User> list = new ArrayList<>(List.of(new User(11,"李四",18),new User(19,"周强强",68),new User(12,"张三",25),new User(13,"张三丰",22),new User(14,"赵四",38))); System.out.println(list); //乱序 Collections.shuffle(list); System.out.println(list); //根据年龄降序 Collections.sort(list,(a,b)->b.getAge()-a.getAge()); System.out.println(list); //根据年龄升序 Collections.sort(list,(a,b)->a.getAge()-b.getAge()); System.out.println(list); } public static void test(String[] args) { List<Integer> list = new ArrayList<>(List.of(10,5,20,6,3,100,200,9)); System.out.println(list); //乱序 Collections.shuffle(list); System.out.println(list); //升序 Collections.sort(list); System.out.println(list); //升序 Collections.sort(list,(a,b)->a-b); System.out.println(list); //降序 Collections.sort(list,(a,b)->b-a); System.out.println(list); //字符串List<String> 排序 List<String> ls = new ArrayList<>(List.of("javascript","c","go","ruby","java","php","python")); System.out.println(ls); Collections.shuffle(ls);//乱序 洗牌 System.out.println(ls); Collections.sort(ls);//升序 System.out.println(ls); Collections.sort(ls, Comparator.reverseOrder());//降序 System.out.println(ls); //字符串根据长度升序 Collections.sort(ls,(a,b)->a.length()-b.length()); System.out.println(ls); //字符串根据长度降序 Collections.sort(ls,(x,y)->y.length()-x.length()); System.out.println(ls);
面试题
(1)我们可以使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。
(2)Iterator只可以向前遍历,而LIstIterator可以双向遍历。
(3)ListIterator从Iterator接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
面试题
-
linkedlist和arraylist和vector区别
同:三个类都实现了List接口。存储数据的特点相同;存储有序的可重复的数据。 异:Vector 古老的实现类,线程安全。但是不常用。 Arraylist 线程不安全。插入删除时效率高。1.5倍扩容。 LinkedList 比Arraylist效率高
//底层
Arraylist 底层使⽤的是 Object 数组;
LinkedList 底层使⽤的是双向链表数据结构。
//是否支持快速随机访问
LinkedList 不⽀持⾼效的随机元素访问,⽽ArrayList⽀持。快速随机访问就是通过元素的序号快速获取元素对象(对应于 get(int index) ⽅法)。
LinkedList删除指定元素时为O(1),而ArrayList为O(n);
ArrayList和Array数组类型转换
Arrays.asList() 可以插入null而List.of不可以
该方法是将数组转化成List集合的方法。
List<String> list = Arrays.asList("a","b","c");
注意:
(1)该方法适用于对象型数据的数组(String、Integer...)
(2)该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean)
(3)该方法将数组与List列表链接起来:当更新其一个时,另一个自动更新
(4)不支持add()、remove()、clear()等方法
//用此方法得到的List的长度是不可改变的,
总结:
如果你的List只是用来遍历,就用Arrays.asList()。
如果你的List还要添加或删除元素,还是乖乖地new一个java.util.ArrayList,然后一个一个的添加元素。
public static void main(String[] args) {
//固定的List
var list1 = Arrays.asList(10,20,30,40);
System.out.println(list1.get(0));
//list1.remove(30);错误
var list2 = List.of(1,2,3);
//list2.clear(); 错误
//list2.add(5);
System.out.println(list2);
//动态List
var list3 = new ArrayList<Integer>();
var list4 = new ArrayList<String>(List.of("java","php","mysql"));
var list5 = new ArrayList<Integer>(Arrays.asList(10,20,30));
list5.add(40);
list4.add("python");
list3.addAll(List.of(11,22,33,44));
System.out.println(list3);
System.out.println(list4);
System.out.println(list5);
//数组转换List
Integer[] nums = new Integer[]{100,200,300};
var list6 = new ArrayList<Integer>(Arrays.asList(nums));
list6.clear();
System.out.println(list6);
//List转换为Array数组
List<String> list7 = new ArrayList<>();
list7.addAll(List.of("java","springmvc","springboot"));
System.out.println(list7.size());
list7.remove("springmvc");
//Object[] ss = list7.toArray();
//System.out.println(Arrays.toString(ss));
String[] ss = new String[list7.size()];
list7.toArray(ss);
System.out.println(list7);
System.out.println(Arrays.toString(ss));
7.2 Collection->Set->HashSet
- Collection->Set->HashSet 实现类
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @Auther Justin-ming
* @Date 2022/1/14 16:39
* set
*/
public class List03 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>(List.of(11,22,33,44,11,66,99));
System.out.println(list.size());
System.out.println(list);
//set无序的不重复的
Set<Integer> set = new HashSet<>(List.of(11, 22, 33, 44, 11, 44, 22, 55, 66, 88));
//lambda表达式遍历
set.forEach(System.out::println);
//for遍历
for (Integer j : set){
System.out.println(j);
}
System.out.println(set.contains(22)); //true
System.out.println(set.containsAll(list)); //是否包含指定集合的所有对象
System.out.println(set.remove(11)); //移除某个元素
}
}
1-9放入-+相加等于100
public static void main(String[] args) {
var set = new HashSet<String>();
while(true){
var s = str();
if(is(s)){
set.add(s);
}
if(set.size()==11){
break;
}
}
for(String t : set){
System.out.printf("%s = 100%n",t);
}
}
public static String str() {
Random rand = new Random();
var list = List.of("", "+", "-");
StringBuilder sbu = new StringBuilder();
for (int i = 1; i < 9; i++) {
sbu.append(String.format("%d%s", i, list.get(rand.nextInt(3))));
}
sbu.append(9);
return sbu.toString();
}
public static boolean is(String s) {
var f = false;
var p = Pattern.compile("[+-]?\\d+");
var m = p.matcher(s);
int sum = 0;
while (m.find()) {
sum += Integer.parseInt(m.group());
}
if (sum == 100) {
f = true;
}
return f;
}
set - > list(双色球)
public static void main(String[] args) {
Random rand = new Random();
Set<Integer> red = new HashSet<>();
while(red.size()<6){
red.add(rand.nextInt(1,34));
}
int blue = rand.nextInt(1,17);
List<List> list = new ArrayList<>();
var list1 = new ArrayList<Integer>(red);
Collections.sort(list1);
var list2 = new ArrayList<Integer>(List.of(blue));
list.add(list1);
list.add(list2);
System.out.println(list);
//Set - List 相互转换
List<Integer> a = new ArrayList<>(List.of(11,22,33,11,44,11,55,11,66));
System.out.println(a);
//List -> Set
Set<Integer> b = new HashSet<>(a);
System.out.println(b);
//Set -> List
List<Integer> c = new ArrayList<>(b);
c.addAll(List.of(11,11,11,222,33));
System.out.println(c);
}
7.3 Map HashMap TreeMap
-
Map<String,Object> map = new HashMap<String,Object>();
-
键值对数据结构的容器集合
-
map.put(k,v);
-
map.get(k);
- HashMap
Book b1 = new Book(100,"java实战",18);
Book b2 = b1;
b2.setPrice(90); //设置价格
sout(b1 == b2); //true
Map<String ,Book> m = new HashMap<>();
m.put("java1",new Book(100,"java",18));
sout(m.containskey("java")); //true
sout(m.containsValue(m.get("java"))); //true
// m.clear();
// m.size();
// m.isEmpty()
// 移除元素
//添加元素时,如果key存在,则值覆盖
map.put("s1", "html");
// 遍历方法二
map.forEach((k, v) -> System.out.printf("%s = %s %n", k, v));
-
map values 排序 keySet() 排序
public static void main(String[] args) { Map<String, Integer> map1 =new HashMap<>(); map1.put("j1",1); map1.put("j2",2); map1.put("j3",3); map1.put("j4",4); //map1.clear(); // 清空 //map1.containsKey("j1"); //map1.containsValue(1); //判断值是否存在 System.out.println(map1.size()); System.out.println(map1.get("j2")); System.out.println(map1.containsKey("j1")); System.out.println(); Collection<Integer> v = map1.values(); System.out.println(v); List<Integer> list = new ArrayList<>(v); Collections.sort(list);//升序 Collections.sort(list,Comparator.reverseOrder()); //将map 的key集合 排序 Set<String> keys = map1.keySet(); List<String> likey = new ArrayList<>(keys); Collections.sort(likey);//默认升序 //降序 Collections.sort(likey, Comparator.reverseOrder()); //Set<String> 是key类型 var k = new ArrayList<>(m.keySet()); System.out.println(k); //list排升序 //k.sort(Comparator.naturalOrder()); //list排降序 //k.sort(Comparator.reverseOrder()); //使用Collections工具类shffle(List) 乱序 //Collections.shuffle(k); //根据字符串长度进行排序 升序 k.sort(Comparator.comparingInt(String::length)); //根据字符串长度进行排序 降序 k.sort((x, y) -> y.length() - x.length()); System.out.println(k); //List<String> 是value类型 var v = new ArrayList<>(m.values()); System.out.println(v); System.out.println(m); } //map1.remove("j1");//指定key,如果key对应两个值就会全部删除 //System.out.println(map1.remove("j2",2)); //指定key并指定值 for(String k : map1.keySet()){ System.out.printf("%s ",k); } }
-
TreeMap
在Map集合框架中,除了HashMap以外,TreeMap也是常用到的集合对象之一。
与HashMap相比,TreeMap是一个能比较元素大小的Map集合,会对传入的key进行了大小排序。其中,可以使用元素的自然顺序,也可以使用集合中自定义的比较器来进行排序;
不同于HashMap的哈希映射,TreeMap实现了红黑树的结构,形成了一颗二叉树。
public static void main(String[] args) {
TreeMap<String, Integer> tm = new TreeMap<>();//自动升序
//Map<String, Integer> tm = new TreeMap<String, Integer>((a, b)-> b-a);//降序
tm.put("java",100);
tm.put("c",200);
tm.put("php",300);
tm.put("python",400);
tm.put("java01",500);
tm.put("java02",500);
System.out.println(tm);//默认升序
System.out.println(tm.keySet());
System.out.println(tm.values());
//遍历
// tm.keySet();
// tm.values();
//Integer 降序
var t = new TreeMap<Integer,String>((a,b)->b-a);
t.put(16,"李四");
t.put(200,"赵六");
t.put(10,"张三丰");
t.put(13,"李勇");
System.out.println(t);
}
面试题
HashMap和TreeMap的区别?
TreeMap:实现了对key的排序默认升序。
//null区别
HashMap可以允许一个null key和多个null value。而TreeMap不允许null key,但是可以允许多个null value。
//性能区别
HashMap的底层是Array,所以HashMap在添加,查找,删除等方法上面速度会非常快。而TreeMap的底层是一个Tree结构,所以速度会比较慢。
另外HashMap因为要保存一个Array,所以会造成空间的浪费,而TreeMap只保存要保持的节点,所以占用的空间比较小。
HashMap如果出现hash冲突的话,效率会变差,不过在java 8进行TreeNode转换之后,效率有很大的提升。
TreeMap在添加和删除节点的时候会进行重排序,会对性能有所影响。
//共同点
两者都不允许duplicate key,两者都不是线程安全的。
八、IO操作
8.1 目录操作
建立目录file.mkdir() file.mkdirs() file.exists() file.isDirectory()
public static void main(String[] args) {
//建立目录
File f = new File("user/jsm.txt");
//isDirectory() 判断是不是目录,不存在返回false,不是目录返回false
System.out.println(f.isDirectory());
if (f.isDirectory())
{
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
//f.delete();//删除空目录,有内容的目录删除不了,也可以删除文件
}else{
//建立目录,建立单极目录
f.mkdir();
//f.mkdirs(); //建立多级目录
}
}
public static void main(String[] args) {
Runtime run = Runtime.getRuntime();
try {
//windows 系统下的cmd
run.exec("cmd /k start http://www.baidu.com");
//删除目录有内容的
run.exec("cmd /k rd /S /Q user\\jsm.txt");
} catch (IOException e) {
e.printStackTrace();
}
/S 除目录本身外,还将删除指定目录下的所有子目录和
文件。用于删除目录树。
/Q 安静模式,带 /S 删除目录树时不要求确认
}
8.2 文件操作
public static void main(String[] args) {
String f = "u.txt";
//建立文件
try(var w = new BufferedWriter(new FileWriter(f,true))) {
Random rand= new Random();
w.write(String.format("%07d[%tF %<tT]",rand.nextInt(1,99999),System.currentTimeMillis()));
} catch (IOException e) {
e.printStackTrace();
}
//读取文件
try(var r = new BufferedReader(new FileReader(f))) {
r.lines().forEach(System.out::println);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//文件复制将u.txt复制到u2.txt
try(var is = new BufferedInputStream(new FileInputStream(f))) {
is.transferTo(new FileOutputStream("u2.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
var file = new File(f);
//文件更名
var fn = file.getName();
fn = "u20220119,txt";
//更名就是(剪切,粘贴。移动文件)
file.renameTo(new File(fn));
file.renameTo(new File("D:\\MY2020.txt"));
//删除文件
if(file.exists()){
file.delete();
}
//文件操作
File f = new File("user");
System.out.println(f.isAbsolute());
System.out.println(f.isDirectory());
System.out.println(f.isHidden());
System.out.println(f.isFile());
System.out.println(f.exists());
//文件最后修改时间
public static void main(String[] args) {
File dir = new File("D:\\idea\\Projects\\maven\\jsm.txt");
System.out.printf("%tF %<tT%n",dir.lastModified());
}
//输出为
2022-01-18 11:46:15
//统计一个文件中的行数 去除空行
/**
* BufferedReader 缓存读取流
* trim 清除空格
* filter 过滤
* e->e Lambda表达式
* lines 是流,只能调用一次
*/
public class File6 {
public static void main(String[] args) throws FileNotFoundException {
String path = "E:\\byshop\\src\\main\\java\\cn\\by\\dao\\GoodsDao.java";
BufferedReader br = new BufferedReader(new FileReader(path));
System.out.println(br.lines().filter(e->e.trim().length()>0).count());
}
}
8.3 字节流
- java.io.InputStream 输入流,主要是用来读取文件内容的。
- java.io.OutputStream 输出流,主要是用来将内容字节写入文件的。
public static void main(String[] args) {
//读取文件
String f = "D:\\java\\log\\20201222-type.txt";
try {
FileInputStream fis = new FileInputStream(f);
//System.out.println(new String(fis.readAllBytes(),"utf-8"));
byte[] buf = new byte[1024];
int len = 0;
while((len = fis.read(buf))>0) {
System.out.println(new String(buf,"utf-8"));
}
fis.close();
}catch(Exception e) {
}
}
public static void write(String str) {
try {
//建立文件输出流,用来写入内容,true,追加模式
FileOutputStream fos = new FileOutputStream("c:/u.txt",true);
fos.write(String.format("hello world 中文效果(%1$tF %1$tT)\r\n", System.currentTimeMillis()).getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
各种流
抽象基类 InputStream、Outputstream、Reader、Writer
文件流(节点流)FileInputStream、FileOutputStream、FileReader、FileWriter
缓冲流参数需要文件流是处理流的一种 BufferedInputStream BufferOutputStream BufferedReader BufferWriter
数据流也是处理流的一种 DataInputStream DataOutputStream
交换流改变字符集时使用也是处理流的一种 InputStreamReader OutputWriter
处理流都要包括文件流但是RandomAccessFile可以不包含直接传入一个文件。RandomAccessFile本身也是一个节点流,文件后面参数指定是作为输入流还是作为读出流。r:只读。rw:读写。rwd:读写更新。rws:读写更新元数据更新。作为输出流的时候写入到文件一些内容会覆盖原有文件内容从头开始覆盖,而不是文件。使用seek方法可以指定位置写入内容,是覆盖而不是插入。但是通过操作也可以实现插入,首先指针移到seek(2)位置。在插入位置之后的内容拿出来存到StringBuild里面,然后指针移到seek(2)位置,写入插入的内容,最后插入StringBuild里面的内容。
对象流用与序列化就是转化(ObjectOutputStream)为二进制文件在各个平台间传输,然后另一个程序拿到之后可以进行反序列化(ObjectInputStream)。不能序列化static和transient修饰的成员变量。
面试题
- java中什么是序列化,反序列化?为什么要序列化?
public class User implements Serializable {
private int id;
private String name;
private String address;
}
public static void main(String[] args) {
//保存对象
//write();
//读取对象
try (var ois = new ObjectInputStream(new FileInputStream("bank.dat"))) {
while (true) {
var a = ois.readObject();
System.out.println(a);
}
} catch (FileNotFoundException e) {
System.out.println("没有bank.dat文件");
} catch (IOException e) {
System.out.println("数据读取完成");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* Description: List<User>
*
* @date: 2022/1/19 10:44
* @params: []
* @return: void
*/
public static void write() {
try (var oo = new ObjectOutputStream(new FileOutputStream("bank.dat", true))) {
var u = new User(100, "李四", "河南郑州");
System.out.println(u);
oo.writeObject(u);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
- 删除目录、拷贝目录、移动目录
public static void main(String[] args) {
//cpDir("D:\\笔记","D:\\笔记1");//复制目录
//move("D:\\笔记","D:\\笔记1");//拷贝移动剪切
delDir("D:\\笔记1"); //删除目录
}
public static void move(String sdir,String ddir){
move(new File(sdir),new File(ddir));
}
public static void move(File sdir,File ddir){
cpDir(sdir,ddir);
delDir(sdir);
}
public static void delDir(String sdir){
delDir(new File(sdir));
}
public static void delDir(File sdir){
File[] fs = sdir.listFiles();
if (fs.length == 0) {
sdir.delete(); //删除空目录
} else {
for (File f : fs) {
if (f.isDirectory()) {
delDir(f);//再次递归调用,删除目录
} else if (f.isFile()) {
f.delete();//删除文件
}
}
}
sdir.delete();
}
public static void cpDir(File sdir , File ddir){
if(!ddir.exists()){
ddir.mkdirs();
}
for(File t : sdir.listFiles()){
if(t.isDirectory()){
cpDir(t,new File(ddir.getPath(),t.getName()));
System.out.println(t);
}else {
try {
Files.copy(t.toPath(), Paths.get(ddir.getPath()+"/"+t.getName()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void cpDir(String sdir,String ddir){
cpDir(new File(sdir),new File(ddir));
}
8.4 ImageIO操作
@SneakyThrows
public static void main(String[] args) {
//建立缓冲图像
var i = new BufferedImage(400,400,2);
//根据缓冲图像,建立画笔2D
var g = i.createGraphics();
//线与文字的平滑度
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
//设置颜色
g.setColor(new Color(255,0,0,100));
//画一个矩形,用设置的颜色填充
g.fillRect(0,0,400,400);
//画直线
g.setStroke(new BasicStroke(2)); //粗细
g.setColor(Color.YELLOW);
g.setColor(new Color(0xff,0xff,0x00));
g.drawLine(0,0,400,400);
g.drawLine(400,0,0,400);
g.drawLine(0,200,400,200);
g.drawLine(200,0,200,400);
//画矩形(空)
g.setColor(new Color(0xff,0xff,0x00));
g.drawRect(150,150,100,100);
//填充透明度
g.setColor(new Color(0xff,0xff,0x00,150));
g.fillRect(100,100,200,200);
//释放画笔占用的内存
g.dispose();
//将画好的缓冲图形,输出到硬盘上"png" 图像格式,new File图像的位置和文件名
ImageIO.write(i,"png",new File("img02.png"));
//调用系统命令,打开保存好的图像
var run = Runtime.getRuntime();
run.exec("cmd /k start img02.png");
}
@SneakyThrows
public static void one (String[] args) {
var width = 300;
var height = 280;
//1,真彩 2,透明度 10,灰度
var img = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
ImageIO.write(img,"jpg",new File("img01.jpg"));
}
public static void main(String[] args) {
//读取文件
var j = ImageIO.read(new File("img01.png"));
var w = j.getWidth();
var h = j.getHeight();
//定义了一个灰度图像,在此图像中所有对象都是黑白的
var k = new BufferedImage(w,h,10);
var g = k.createGraphics();
//使用画笔将src图像,话黑白图像中,就没有彩色了
g.drawImage(j,0,0,null);
g.dispose();
ImageIO.write(k,"png", new File("img02.png"));
Runtime.getRuntime().exec("cmd /k start img01.png");
Runtime.getRuntime().exec("cmd /k start img02.png");
九、lambda
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑,有效避免内部匿名类出现
函数式接口(这样的接口有且只有一个抽象方法)
9.1 函数式接口
序号 | 接口 & 描述 |
---|---|
1 | **BiConsumer<T,U>**代表了一个接受两个输入参数的操作,并且不返回任何结果 |
2 | **BiFunction<T,U,R>**代表了一个接受两个输入参数的方法,并且返回一个结果 |
3 | **BinaryOperator**代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果 |
4 | **BiPredicate<T,U>**代表了一个两个参数的boolean值方法 |
5 | BooleanSupplier代表了boolean值结果的提供方 |
6 | **Consumer**代表了接受一个输入参数并且无返回的操作 |
7 | DoubleBinaryOperator代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。 |
8 | DoubleConsumer代表一个接受double值参数的操作,并且不返回结果。 |
9 | **DoubleFunction**代表接受一个double值参数的方法,并且返回结果 |
10 | DoublePredicate代表一个拥有double值参数的boolean值方法 |
11 | DoubleSupplier代表一个double值结构的提供方 |
12 | DoubleToIntFunction接受一个double类型输入,返回一个int类型结果。 |
13 | DoubleToLongFunction接受一个double类型输入,返回一个long类型结果 |
14 | DoubleUnaryOperator接受一个参数同为类型double,返回值类型也为double 。 |
15 | **Function<T,R>**接受一个输入参数,返回一个结果。 |
16 | IntBinaryOperator接受两个参数同为类型int,返回值类型也为int 。 |
17 | IntConsumer接受一个int类型的输入参数,无返回值 。 |
18 | **IntFunction**接受一个int类型输入参数,返回一个结果 。 |
19 | IntPredicate:接受一个int输入参数,返回一个布尔值的结果。 |
20 | IntSupplier无参数,返回一个int类型结果。 |
21 | IntToDoubleFunction接受一个int类型输入,返回一个double类型结果 。 |
22 | IntToLongFunction接受一个int类型输入,返回一个long类型结果。 |
23 | IntUnaryOperator接受一个参数同为类型int,返回值类型也为int 。 |
24 | LongBinaryOperator接受两个参数同为类型long,返回值类型也为long。 |
25 | LongConsumer接受一个long类型的输入参数,无返回值。 |
26 | **LongFunction**接受一个long类型输入参数,返回一个结果。 |
27 | LongPredicateR接受一个long输入参数,返回一个布尔值类型结果。 |
28 | LongSupplier无参数,返回一个结果long类型的值。 |
29 | LongToDoubleFunction接受一个long类型输入,返回一个double类型结果。 |
30 | LongToIntFunction接受一个long类型输入,返回一个int类型结果。 |
31 | LongUnaryOperator接受一个参数同为类型long,返回值类型也为long。 |
32 | **ObjDoubleConsumer**接受一个object类型和一个double类型的输入参数,无返回值。 |
33 | **ObjIntConsumer**接受一个object类型和一个int类型的输入参数,无返回值。 |
34 | **ObjLongConsumer**接受一个object类型和一个long类型的输入参数,无返回值。 |
35 | **Predicate**接受一个输入参数,返回一个布尔值结果。 |
36 | **Supplier**无参数,返回一个结果。 |
37 | **ToDoubleBiFunction<T,U>**接受两个输入参数,返回一个double类型结果 |
38 | **ToDoubleFunction**接受一个输入参数,返回一个double类型结果 |
39 | **ToIntBiFunction<T,U>**接受两个输入参数,返回一个int类型结果。 |
40 | **ToIntFunction**接受一个输入参数,返回一个int类型结果。 |
41 | **ToLongBiFunction<T,U>**接受两个输入参数,返回一个long类型结果。 |
42 | **ToLongFunction**接受一个输入参数,返回一个long类型结果。 |
43 | **UnaryOperator**接受一个参数为类型T,返回值类型也为T。一元运算,接受一个T类型参数,输出一个与入参一模一样的值 |
接口 | 参数 | 返回内容 | 描述 |
---|---|---|---|
Predicate java.util.function.Predicate | T | boolean | 用于判别一个对象。比如求一个人是否为男性 |
Consumer 消费型 | T | void | 用于接收一个对象进行处理但没有返回,比如接收一个人并打印他的名字 |
Function<T, R> 函数型 | T | R | 转换一个对象为不同类型的对象 |
Supplier 供给型 | None | T | 提供一个对象 |
UnaryOperator | T | T | 接收对象并返回同类型的对象 |
BinaryOperator | (T, T) | T | 接收两个同类型的对象,并返回一个原类型对象 |
9.2 Stream流技术
Stream(流)是一个来自数据源的元素队列并支持聚合操作,比集合快,但是只执行一次。
- 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
- 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
面试题
//面试题计算1到100 的值。使用IntStream流
var s = IntStream.rangeClosed(1,100);
System.out.println("1+2+...+100="+s.sum());
- IntSream
public static void main(String[] args) {
var rand = new Random();
var is = IntStream.generate(()-> rand.nextInt(1,101)).limit(5).skip(1);//跳出一个数
// is.forEach(System.out::println);
//升序输出
// is.sorted().forEach(System.out::println);
//降序输出
//is.boxed().sorted((a,b)->b-a).forEach(System.out::println);
//乱序
Stream<Integer> ss = is.boxed();
ss.sorted((a,b)->Math.random() > .5?1:-1).forEach(System.out::println);
//IntStream 相当于 Stream<Integer>
}
public static void main2(String[] args) {
//生产一个intstream流,数据为随机整数1-100
Random rand = new Random();
//rand.nexint生成5个整数
var is = IntStream.generate(() -> rand.nextInt(1,101)).limit(10);
is.forEach(System.out::println);
//生成5个随即小数
var is1 = DoubleStream.generate(Math::random).limit(5);
is1.forEach(System.out::println);//循环完成之后流就结束了,一次性的。
//1,3,5,7,9
// IntStream.iterate(1, a->a+2).limit(5).forEach(System.out::println);
IntConsumer j = System.out::println;
var is2= IntStream.iterate(10,a->a+10).limit(5);
Stream<Integer> ll = is2.boxed();
}
public static void main1(String[] args) {
IntStream is = IntStream.empty();
var is1= IntStream.of(1,2,3);//3个元素
var is2 = IntStream.of(10);//1
var is3 = IntStream.range(1,3);//2
var is4 = IntStream.rangeClosed(1,100);//100
var is5 = IntStream.iterate(1,e ->e+2).limit(5);//1.3.5.7.9
is5.forEach(System.out::println);
-
Option容器
-
option是一个可以为null的容器对象。如果值存在则isPewsent()方法会返回true,调用get()方法会返回该对象。 Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测 Optional 类的引入很好的解决空指针异常。
序号 方法 & 描述 1 **static Optional empty()**返回空的 Optional 实例。 2 **boolean equals(Object obj)**判断其他对象是否等于 Optional。 3 **Optional filter(Predicate<? super predicate)**如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。 4 ** Optional flatMap(Function<? super T,Optional> mapper)**如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional 5 **T get()**如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException 6 **int hashCode()**返回存在值的哈希码,如果值不存在 返回 0。 7 **void ifPresent(Consumer<? super T> consumer)**如果值存在则使用该值调用 consumer , 否则不做任何事情。 8 **boolean isPresent()**如果值存在则方法会返回true,否则返回 false。 9 **Optional map(Function<? super T,? extends U> mapper)**如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。 10 **static Optional of(T value)**返回一个指定非null值的Optional。 11 **static Optional ofNullable(T value)**如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。 12 **T orElse(T other)**如果存在该值,返回值, 否则返回 other。 13 **T orElseGet(Supplier<? extends T> other)**如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。 14 ** T orElseThrow(Supplier<? extends X> exceptionSupplier)**如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 15 **String toString()**返回一个Optional的非空字符串,用来调试
注意事项:
Optional
无法被序列化。所以不要试图将Optional
作为方法参数进行定义,也不要在类当中声明Optional
类型的成员变量。Optional
通常只作为方法的返回值,用来规避空指针异常。在使用
Optional
时,应该使用函数式的编程风格。
十、多线程概念
什么是程序?一个程序可以有多个进程
程序是一段静态的代码,它是应用程序执行的蓝本。
什么是进程?一个进程可以有多线程
进程是指一种正在运行的程序,有自己的地址空间。
作为蓝本的程序可以被多次加载到系统的不同内存区域分别执行,形成不同的进程。
基于进程的特点是允许计算机同时运行两个或更多的程序。
什么是线程?
线程是进程内部单一的一个顺序控制流。 一个进程在执行过程中,可以产生多个线程。每个线程也有自己产生、存在和消亡的过程。
并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。
并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
区别:并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。倘若在计算机系统中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。
10.1 JUC
在 Java 5.0 提供了 java.util.concurrent
(简称JUC)包,在此包中增加了在并发编程中很常用的工具类,
用于定义类似于线程的自定义子系统,包括线程池,异步 IO 和轻量级任务框架;还提供了设计用于多线程上下文中
的 Collection 实现等
10.2 实现多线程类的方法
10.2.1 Runable接口 Thread类 Callable接口
实现Runable接口run方法即可。
继承Thread类并实现run方法。
实现Callable接口run方法。
卖票
/**
* @Auther Justin-ming
* @Date 2022/1/27 9:25
* 线程
*/
public class Theadss5 {
public static void main(String[] args) {
var t = new Ticket(20);
var t1 = new Thread(t,"j");
var t2= new Thread(t,"s");
var t3 = new Thread(t,"m");
t2.start();
t1.start();
t3.start();
}
}
/**
* @Auther Justin-ming
* @Date 2022/1/27 11:56
*/
public class Ticket implements Runnable {
private int num = 100;
public Ticket() {
}
public Ticket(int num) {
this.num = num;
}
@Override
public void run() {
String t = Thread.currentThread().getName();
System.out.printf("%s开启--", t);
while (true) {
synchronized (this) {
if (num < 1) {
break;
}
System.out.printf("%s卖出一张票:剩余%d%n", t, --num);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.printf("%s结束", t);
}
}
10.3 多线程状态及常用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ciOAtaW-1645837761041)(C:\Users\Jsm\AppData\Roaming\Typora\typora-user-images\image-20220128175131189.png)]
java中线程优先级:10个级别
定时操作
/ new Thread(()->{
// Long j = System.currentTimeMillis();
// while(true){
// Long k = System.currentTimeMillis()-j;
// if (k >= 10*1000){break;}
// }
// System.out.println("关机啦");
// }).start();
// new Thread(()->{
// try {
// TimeUnit.SECONDS.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }).start();
new Thread(()->{
String s = "2022-01-28 21:35:50";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long end = 0;
try {
TimeUnit.MILLISECONDS.sleep(end - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s",s);
}).start();
-
TimeUnit
TmieUtil.Day.toMills(1)//一天有多少毫秒 TimeUtil.SECONDS.sleep(5)//5s TimeUtil.MINUTES.sleep(5)//5m
Timer类的常用其他方法:
cancel()
终止此计时器,丢弃所有当前已安排的任务。purge()
从此计时器的任务队列中移除所有已取消的任务。schedule(TimerTask task, Date time)
安排在指定的时间执行指定的任务。TimerTask类的常用其他方法:
cancel()
取消此计时器任务。run()
此计时器任务要执行的操作。scheduledExecutionTime()
返回此任务最近行的已安排执行时间。
面试题
1、A线程正在执行一个对象中的同步方法,B线程是否可以同时执行同一个对象中的非同步方法? `可以`
2、同上,B线程是否可以同时执行同一个对象中的另一个同步方法?不可以
3、线程抛出异常会释放锁吗?会的
4、volatile和synchronized区别?
5、写一个程序,证明AtomXXX类比synchronized更高效
6、AtomXXX类可以保证可见性吗?请写一个程序来证明 可以
7、写一个程序证明AtomXXX类的多个方法并不构成原子性
8、写一个程序模拟死锁
9、写一个程序,在main线程中启动100个线程,100个线程完成后,主线程打印“完成”,使用join()和countdownlatch都可以完成,请比较异同,循环栅栏。
答案参考:https://blog.csdn.net/cckevincyh/article/details/103845640
10.4 ReentrantLock公平锁
Lock lock =new RenntrantLock(true);
lock.lock();//加锁
lock.unlock();//解锁
十一、注解Annotation
11.1 内置注解
一共有7个。
@Override //重写
@Deprecated //告诉开发人员此方法已经过时.如果使用此方法会编译错误
@SuppressWarnings //忽略警告
关键字 | 用途 |
---|---|
all | to suppress all warnings(抑制所有警告) |
boxing | to suppress warnings relative to boxing/unboxing operations(要抑制与箱/非装箱操作相关的警告) |
cast | to suppress warnings relative to cast operations(为了抑制与强制转换操作相关的警告) |
dep-ann | to suppress warnings relative to deprecated annotation(要抑制相对于弃用注释的警告) |
deprecation | to suppress warnings relative to deprecation(要抑制相对于弃用的警告) |
fallthrough | to suppress warnings relative to missing breaks in switch statements(在switch语句中,抑制与缺失中断相关的警告) |
finally | to suppress warnings relative to finally block that don’t return(为了抑制警告,相对于最终阻止不返回的警告) |
hiding | to suppress warnings relative to locals that hide variable(为了抑制本地隐藏变量的警告) |
incomplete-switch | to suppress warnings relative to missing entries in a switch statement (enum case)(为了在switch语句(enum案例)中抑制相对于缺失条目的警告) |
nls | to suppress warnings relative to non-nls string literals(要抑制相对于非nls字符串字面量的警告) |
null | to suppress warnings relative to null analysis(为了抑制与null分析相关的警告) |
rawtypes | to suppress warnings relative to un-specific types when using generics on class params(在类params上使用泛型时,要抑制相对于非特异性类型的警告) |
restriction | to suppress warnings relative to usage of discouraged or forbidden references(禁止使用警告或禁止引用的警告) |
serial | to suppress warnings relative to missing serialVersionUID field for a serializable class(为了一个可串行化的类,为了抑制相对于缺失的serialVersionUID字段的警告) |
static-access | o suppress warnings relative to incorrect static access(o抑制与不正确的静态访问相关的警告) |
synthetic-access | to suppress warnings relative to unoptimized access from inner classes(相对于内部类的未优化访问,来抑制警告) |
unchecked | to suppress warnings relative to unchecked operations(相对于不受约束的操作,抑制警告) |
unqualified-field-access | to suppress warnings relative to field access unqualified(为了抑制与现场访问相关的警告) |
unused | to suppress warnings relative to unused code(抑制没有使用过代码的警告) |
11.1 元注解
写注解类用
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Documented - 标记这些注解是否包含在用户文档中。
@Target - 标记这个注解应该是哪种 Java 成员。
@Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
//如何定义
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@interface Anns{
Ann[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Repeatable(Anns.class)
public @interface Ann {
String name();
int age();
}
//使用
@Ann(age = 18,name="jsm")
@Ann(age = 19,name="jsm1")
public class AnnTest {
public static void main(String[] args) {
var a = AnnTest.class;
if (a.isAnnotationPresent(Anns.class)){
var b = a.getAnnotation(Anns.class).value();
System.out.println(b[0].name());
System.out.println(b[0].age());
System.out.println(b[1].name());
System.out.println(b[1].age());}}}
十二、java1.8日期API
|LocaleDate
//LocaleDate
// LocalDate d = LocalDate.now();
// System.out.println(d);
//System.out.printf("%tF",d);
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// LocalDate d2 = LocalDate.MAX;
LocalDate d3 = LocalDate.of(1998,3,4);//指定 生日
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
System.out.println(dtf.format(d3));
System.out.println(d3);
System.out.println(d3.getDayOfMonth());//返回月
System.out.println(d3.isLeapYear());//判断是不是闰年返回true
System.out.printf("%tA%n",d3.getDayOfWeek());//返回星期
System.out.println(d3.getDayOfYear());//这年的第几天
System.out.println();
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINA));//星期三
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.CHINA));//周三
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.US));//Wednesday
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.US));//web
System.out.println();
@Test
@DisplayName("LocalDateTime2")
public void m8(){
var n = LocalDate.now();
//本月第一天
System.out.println(n.with(TemporalAdjusters.firstDayOfMonth()));
//最后一天
System.out.println(n.with(TemporalAdjusters.lastDayOfMonth()));
//下月第一天
System.out.println(n.with(TemporalAdjusters.firstDayOfNextMonth()));
//上月第一天
System.out.println(n.minus(1,ChronoUnit.MONTHS).with(TemporalAdjusters.firstDayOfMonth()));
//判断闰年
var d = LocalDate.parse("19980304",DateTimeFormatter.ofPattern("yyyyMMdd"));
System.out.println(d.isLeapYear());
Year y = Year.now();
System.out.println(y.isLeap());
}
@Test
@DisplayName("LocalDateTime1")
public void m7(){
var d = LocalDate.now();
var d1 = LocalDate.of(1998,3,4);
var days = d1.until(d,ChronoUnit.DAYS);
System.out.println(days);
//两个日期间隔多少天
var days1 = Duration.between(d1.atStartOfDay(),d.atStartOfDay()).toDays();
System.out.println(days1);
//两个日期间隔多少天
var days2 = ChronoUnit.DAYS.between(d1, d);
System.out.println(ChronoUnit.YEARS.between(d1, d));
System.out.println(days2);
//
var days3 = Period.between(d1,d);
System.out.println(days3.getYears());
System.out.println(days3.getMonths());
System.out.println(days3.getDays());
}
@Test
@DisplayName("LockDateTime")
public void m6(){
var n1 = LocalDateTime.now(ZoneId.of("GMT+0"));
var n = LocalDateTime.now();
var f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(n.format(f));
// System.out.println(n.toLocalDate());
// System.out.println(n.toLocalTime());
//秒
System.out.println(n.toEpochSecond(ZoneOffset.of("+8")));
//毫秒
System.out.println(n.toInstant(ZoneOffset.of("+8")).toEpochMilli());
}
@Test
@DisplayName("LocakTime运算")
public void m4(){
// LocalTime time = LocalTime.now();
LocalTime time = LocalTime.of(12,0,0);
System.out.println(time.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
}
@Test
@DisplayName("LocakDate运算")
public void m3(){
var d = LocalDate.now();
//d = d.plusDays(19);//日期增加35天
d = d.plus(5, ChronoUnit.DAYS);//增加几天
System.out.println(d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
var d2 = LocalDate.parse("1998-03-04",DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(d2);
}
@Test
@DisplayName("JAVA8 LocaleDate")
public void m2(){
//LocaleDate
// LocalDate d = LocalDate.now();
// System.out.println(d);
//System.out.printf("%tF",d);
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// LocalDate d2 = LocalDate.MAX;
LocalDate d3 = LocalDate.of(1998,3,4);//指定 生日
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
System.out.println(dtf.format(d3));
System.out.println(d3);
System.out.println(d3.getDayOfMonth());//返回月
System.out.println(d3.isLeapYear());//判断是不是闰年返回true
System.out.printf("%tA%n",d3.getDayOfWeek());//返回星期
System.out.println(d3.getDayOfYear());//这年的第几天
System.out.println();
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINA));//星期三
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.CHINA));//周三
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.US));//Wednesday
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.US));//web
System.out.println();
}
@SneakyThrows
@Test
@DisplayName("时间挫")
public void m1(){
// System.out.println("ok");
System.out.println(System.currentTimeMillis());
//System.out.printf("%tF %<tT",1644455300746l);
System.out.printf("%tF %<tT%n",0l);
System.out.printf("%tF %<tT%n",Long.MAX_VALUE);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
System.out.println(sdf.format(d));
System.out.println(sdf.parse("2022-02-10 09:14:32").getTime());//换为时间挫
Calendar c = Calendar.getInstance();
Date d1 = c.getTime();//转date
System.out.printf("%tF %<tT%n",d1);
long l = c.getTimeInMillis();//转时间挫
intln(n.toLocalTime());
//秒
System.out.println(n.toEpochSecond(ZoneOffset.of("+8")));
//毫秒
System.out.println(n.toInstant(ZoneOffset.of("+8")).toEpochMilli());
}
@Test
@DisplayName("LocakTime运算")
public void m4(){
// LocalTime time = LocalTime.now();
LocalTime time = LocalTime.of(12,0,0);
System.out.println(time.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
}
@Test
@DisplayName("LocakDate运算")
public void m3(){
var d = LocalDate.now();
//d = d.plusDays(19);//日期增加35天
d = d.plus(5, ChronoUnit.DAYS);//增加几天
System.out.println(d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
var d2 = LocalDate.parse("1998-03-04",DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(d2);
}
@Test
@DisplayName("JAVA8 LocaleDate")
public void m2(){
//LocaleDate
// LocalDate d = LocalDate.now();
// System.out.println(d);
//System.out.printf("%tF",d);
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// LocalDate d2 = LocalDate.MAX;
LocalDate d3 = LocalDate.of(1998,3,4);//指定 生日
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
System.out.println(dtf.format(d3));
System.out.println(d3);
System.out.println(d3.getDayOfMonth());//返回月
System.out.println(d3.isLeapYear());//判断是不是闰年返回true
System.out.printf("%tA%n",d3.getDayOfWeek());//返回星期
System.out.println(d3.getDayOfYear());//这年的第几天
System.out.println();
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINA));//星期三
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.CHINA));//周三
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.US));//Wednesday
System.out.println(d3.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.US));//web
System.out.println();
}
@SneakyThrows
@Test
@DisplayName("时间挫")
public void m1(){
// System.out.println("ok");
System.out.println(System.currentTimeMillis());
//System.out.printf("%tF %<tT",1644455300746l);
System.out.printf("%tF %<tT%n",0l);
System.out.printf("%tF %<tT%n",Long.MAX_VALUE);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
System.out.println(sdf.format(d));
System.out.println(sdf.parse("2022-02-10 09:14:32").getTime());//换为时间挫
Calendar c = Calendar.getInstance();
Date d1 = c.getTime();//转date
System.out.printf("%tF %<tT%n",d1);
long l = c.getTimeInMillis();//转时间挫