Java进阶笔记(面向对象后, 持续更新)

常用API

游戏打包成exe

考虑的因素

  1. 要有图形化界面
  2. 代码要打包起来
  3. 游戏用到的图片也要打包
  4. JDK也要打包

核心步骤

  1. 把所有代码打包成一个压缩包, jar后缀的压缩包
  2. 把jar包转换成exe安装包
  3. 把第二部的exe, 图片, JDK整合在一起, 变成最终的exe安装包

1. Math

  • 是一个帮助我们用于进行数学计算的工具类
  • 私有化构造方法, 所有方法都是静态的
常用方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看一下Math源码:

public final class Math {/*** Don't let anyone instantiate this class.*/private Math() {}/*** The {@code double} value that is closer than any other to* <i>e</i>, the base of the natural logarithms.*/public static final double E = 2.718281828459045;/*** The {@code double} value that is closer than any other to* <i>pi</i> (&pi;), the ratio of the circumference of a circle to* its diameter.*/public static final double PI = 3.141592653589793;

扩展:

Math.sqrt() 开平方

Math.cbrt() 开立方

2. System

工具类, 提供了一些与系统相关的方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

计算机中的时间原点: 19070-1-1 00:00:00 (C语言的生日)

1秒 = 1 000毫秒 = 1 000 000微秒 = 1 000 000 000 纳秒

代码演示:

package APIDemo1;public class SystemDemo {public static void main(String[] args) {// 0-当前虚拟机正常停止// 非0- 异常停止//System.exit(0);//        long l = System.currentTimeMillis();
//        System.out.println(l);//test01();test02();}public static void test01(){// 判断1-10000之间有多少质数int count = 0;long time1 = System.currentTimeMillis();for (int i = 1; i <= 100000; i++) {if(isPrime1(i)) ++count;}long time2 = System.currentTimeMillis();System.out.println(count);long time3 = time2 - time1;System.out.println("算法1花费: " + time3);System.out.println("--------------------------------");count = 0;long time4 = System.currentTimeMillis();for (int i = 1; i <= 100000; i++) {if(isPrime2(i)) ++count;}long time5 = System.currentTimeMillis();System.out.println(count);long time6 = time5 - time4;System.out.println("算法2花费: " + time6);}public static boolean isPrime1(int number){for(int i = 2; i < number; ++i){if(number % i == 0){return false;}}return true;}public static boolean isPrime2(int number){for(int i = 2; i <= Math.sqrt(number); ++i){if(number % i == 0){return false;}}return true;}public static void test02(){int[] arr1 = {1,2,3,4,5,6,7,8,9,10};int[] arr2 = new int[10];// 把arr1拷贝到arr2中// 参数一: 数据源// 参数二: 拷贝起始索引// 参数三: 目标数组// 参数四: 目的地数组的索引// 参数五: 拷贝的个数// 现在想要 0 0 7 8 9 0 0 0 0 0System.arraycopy(arr1, 6, arr2, 2, 3);for (int i = 0; i < arr2.length; i++) {System.out.print(arr2[i] + " ");}System.out.println();}
}

扩展

  1. 如果数据源数组和目的地数组都是基本数据类型, 那么两者的类型必须保持一致
    比如arr1是int数组, arr2是double数组的话就不能拷贝
  2. 拷贝的时候要考虑数组长度, 超出范围也会报错
  3. 如果数据源数组和目的地数组都是引用数据类型
    那么子类数据类型可以赋值给父类类型 arr1里面的类型是子类, arr2是父类 就可以

3. Runtime

Runtime表示当前虚拟机的运行环境

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package APIDemo1;import java.io.IOException;public class RuntimeDemo {public static void main(String[] args) throws IOException {// 1. 获取Runtime对象// 这个类只能获取一个对象, 所以多次调用得到的对象也是一致的Runtime r1 = Runtime.getRuntime();Runtime r2 = Runtime.getRuntime();//System.out.println(r1 == r2); // true// 2. exit//Runtime.getRuntime().exit(0); // System.exit(0) 就是这么调用的//System.out.println("看看我执行了吗");// 3. CPU线程数System.out.println(r1.availableProcessors()); // 12// 4. 总内存大小 byteSystem.out.println(r1.maxMemory() / 1024 / 1024); // 单位是M// 5. 已经获取的总内存大小System.out.println(r1.totalMemory() / 1024 / 1024);// 6. 剩余内存大小System.out.println(r1.freeMemory() / 1024 / 1024);// 7. 运行cmd命令Runtime.getRuntime().exec("notepad"); // 运行记事本// shutdown: 关机// 加上参数才能执行// -s : 默认在1分钟后关机// -s -t 指定时间: t单位是秒// -a: 取消关机操作// -r: 关机并重启Runtime.getRuntime().exec("shutdown -a");}
}

4. Object 和 Objects

object

  • Object是Java的顶级父类. 所有的累都直接或间接继承于Object类
  • Object类中的方法可以被所有子类访问, 所以我们要学习Object类和其中的方法
构造方法

只有空参构造

成员方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

toString
package ObjectDemo1;public class ObjectDemo1 {public static void main(String[] args) {Object obj = new Object();String str = obj.toString();System.out.println(str); //java.lang.Object@b4c966a// System是类名// out: 静态变量// System.out: 获取打印的对象// println(): 方法// 参数: 表示打印的内容// 核心逻辑:// 当打印一个对象的时候, 看底层会调用对象的toString方法// 把对象变成字符串// 然后再打印在控制台, 打印完毕换行处理System.out.println(obj); //java.lang.Object@b4c966aStudent s = new Student("ljq", 24);System.out.println(s);}
}

默认情况下, 打印一个对象打印的就是地址值, 如果想打印对象里面的属性, 可以重写toString方法( ptg to JavaBean )

在重写的方法中, 把要返回的字符串拼接好返回即可

equals

比较两个对象是否相等

返回布尔类型

默认比较地址值, 所以两个空的新建的对象是不相等的

解决方法: 重写父类的equals方法

重写toString 和 equals方法
public String toString() {return "Student{name = " + name + ", age = " + age + "}";
}@Override
public boolean equals(Object o) {if (this == o) return true; // 比较地址值是否相等, 相等的话直接返回trueif (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;// 比较每个成员属性return age == student.age && Objects.equals(name, student.name);
}@Override
public int hashCode() {return Objects.hash(name, age);
}
小练习
package ObjectDemo1;public class ObjectDemo2 {public static void main(String[] args) {String s = "abc";StringBuilder sb = new StringBuilder("abc");System.out.println(s.equals(sb)); // falseSystem.out.println(sb.equals(s)); // false}
}

解释:

  1. System.out.println(s.equals(sb)); // false

因为equals方法是s调用的, s是字符串, 所以equals要看String类中的方法

源码如下:

public boolean equals(Object anObject) {if (this == anObject) {return true;}return (anObject instanceof String aString)&& (!COMPACT_STRINGS || this.coder == aString.coder)&& StringLatin1.equals(value, aString.value);
}

该方法会先判断参数是否为字符串, 如果是字符串, 在比较内部的属性, 如果不是, 直接返回false

该题sb是StringBuilder对象, 不是String对象, 所以返回false.

  1. System.out.println(sb.equals(s)); // false

这里的equals方法是sb调用的, 所以要看StringBuilder方法里的equals方法.

但是StringBuilder里没有该方法, 所以用的是Object父类的equals方法, 即直接比较两个对象的地址值, 直接返回false.

clone

对象克隆

把A对象里面的属性值完全拷贝给B对象, 也叫对象拷贝, 对象赋值

代码:

User的JavaBean

package ObjectDemo1;import java.util.StringJoiner;public class User implements Cloneable{private String name;private int age;private int[] data;public User() {}public User(String name, int age, int[] data) {this.name = name;this.age = age;this.data = data;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}/*** 获取* @return data*/public int[] getData() {return data;}/*** 设置* @param data*/public void setData(int[] data) {this.data = data;}public String toString() {return "User{name = " + name + ", age = " + age + ", data = " + arrToString(data) + "}";}private String arrToString(int[] data){StringJoiner sj = new StringJoiner(",", "[", "]");for (int i = 0; i < data.length; i++) {sj.add(data[i] + "");}return sj.toString();}@Overrideprotected Object clone() throws CloneNotSupportedException {// 调用父类中的clone方法return super.clone();}
}

Test代码

package ObjectDemo1;public class TestUser {public static void main(String[] args) throws CloneNotSupportedException {int[] data = {1,2,3,4,5};User u1 = new User("ljq", 12, data);User u2 = (User) u1.clone();System.out.println(u1);System.out.println(u2);}
}

细节:

方法在底层会给我们创建一个对象, 并把原对象中的数据拷贝过去

User类需要实现一个没有抽象方法的接口

解释:

如果一个接口里面没有抽象方法, 表示当前的接口是一个标记性接口

现在Cloneable表示一旦实现了, 那么当前类就可以被克隆

如果没有实现, 当前类的对象就不能克隆

书写细节:

  1. 重写Object中的clone方法
  2. 让Javabean类实现cloneable接口
  3. 创建原对象并调用clone就可以了

两种克隆方式

浅克隆, 浅拷贝

不管对象内部的属性是基本数据类型还是引用数据类型, 都完全拷贝过来

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

深克隆, 深拷贝

基本数据类型拷贝过来

字符串复用串池里的数据

引用数据类型会创建新的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Object里的clone方法是浅克隆

验证:

int[] arr = u1.getData();
arr[0] = 100;System.out.println(u1);
System.out.println(u2);

两个对象里的data数据都改变了.

怎么实现深克隆?

@Override
protected Object clone() throws CloneNotSupportedException {// 调用父类中的clone方法// 相当于让Java帮我们克隆一个对象, 并把克隆之后的对象返回出去// 先把被克隆对象中的数组获取出来int[] data = this.data;// 创建新的数组int[] newData = new int[data.length];// 拷贝数组中的数据for (int i = 0; i < data.length; i++) {newData[i] = data[i];}// 调用父类中的方法克隆User u = (User)super.clone();// 因为父类中的克隆方法是浅克隆, 替换克隆出来对象中的数组地址值u.data = newData;return u;
}

扩展:

第三方工具类 自带深克隆方法

Gson

Objects

工具类

Object的equals方法, 需要先判断对象是否为null, 因为空对象无法调用成员函数

构造方法

Objects 类的构造方法是私有的,因此无法直接通过实例化对象的方式来调用构造方法。

成员方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

成员方法代码演示
package Objects;import java.util.Objects;public class ObjectsDemo1 {public static void main(String[] args) {Student s1 = new Student("zhangsan", 23);Student s2 = null;//System.out.println(s1.equals(s2));// s2.equals(s1); // 会报错boolean res1 = Objects.equals(s1, s2);System.out.println(res1); // falseSystem.out.println(Objects.isNull(s1)); // falseSystem.out.println(Objects.isNull(s2)); // trueSystem.out.println(Objects.nonNull(s1)); // trueSystem.out.println(Objects.nonNull(s2)); // false}
}

equals方法细节:

  1. 方法的底层会判断s2是否为null, 如果是null, 直接返回false
  2. 如果s2不是null, 那么就利用s2再次调用equals方法
  3. 此时s2是student类型, 所以最终还是会调用Student中的equals方法

如果equals方法没有被重写的话, 就比较地址值, 重写了就比较属性值.

5. BigInteger 和 BigDecimal

BigInteger

java中整数的四种类型及所占用的字节数

byte 1 , short 2 , int 4 , long 8

构造方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对象一旦创建, 内部的值就不能发生改变(只要进行计算, 就会产生一个新的BigInteger对象)

package BigInteger;import java.math.BigInteger;
import java.util.Random;public class BigIntegerDemo {public static void main(String[] args) {// 获取一个随机的大整数BigInteger bd1 = new BigInteger(4, new Random());System.out.println(bd1);// 获取指定的大整数// 字符串里面必须是整数, 不能有小数或字母BigInteger bd2 = new BigInteger("99999999999999999999999999");System.out.println(bd2);// 获取指定进制的大整数// 字符串的数字必须为整数// 且必须与进制吻合BigInteger bd3 = new BigInteger("1001", 2);System.out.println(bd3);// 静态方法获取大整数BigInteger bd4 = BigInteger.valueOf(16);BigInteger bd5 = BigInteger.valueOf(16);System.out.println(bd4 == bd5); // true// 获取最大Long类型的值System.out.println(Long.MAX_VALUE);}
}

常用的方法是2 和 4

方法4 与 2相比:

  1. 能表示的范围在long之内, 比方法2小
  2. 在内部常用的数字: -16 ~ +16 进行了优化
  3. 提前把这个范围内的数字创建好BigInteger的对象, 如果多次获取不会创建新的对象
成员方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码:

package BigInteger;import java.math.BigInteger;public class BigIntegerDemo2 {public static void main(String[] args) {// 1.创建两个对象BigInteger bd1 = BigInteger.valueOf(10);BigInteger bd2 = BigInteger.valueOf(2);// 2.加法BigInteger bd3 = bd1.add(bd2);System.out.println(bd3);// 3.除法 获取商和余数BigInteger[] arr1 = bd1.divideAndRemainder(bd2);System.out.println(arr1.length); // 2System.out.println(arr1[0]); // 5System.out.println(arr1[1]); // 0// 4.比较是否相同// 结果// true 当且仅当指定的Object是BigInteger时,// 其值在数字上等于此BigIntegerSystem.out.println(bd1.equals(bd2));// 5.次幂BigInteger bd4 = bd1.pow(2);System.out.println(bd4);// 6.maxBigInteger bd5 = bd1.max(bd2);System.out.println(bd5.equals(bd1)); // trueSystem.out.println(bd5.equals(bd2)); // false// 7.转换为int类型整数// 超出范围会出现错误BigInteger bd6 = BigInteger.valueOf(1000);int i = bd6.intValue();System.out.println(i);}
}
底层存储方式
  1. 对于计算机而言, 是没有数据类型的概念的, 都是010101
  2. 数据类型是编程语言自己规定的

源码:

public class BigInteger extends Number implements Comparable<BigInteger> {/*** The signum of this BigInteger: -1 for negative, 0 for zero, or* 1 for positive.  Note that the BigInteger zero <em>must</em> have* a signum of 0.  This is necessary to ensures that there is exactly one* representation for each BigInteger value.*/final int signum;/*** The magnitude of this BigInteger, in <i>big-endian</i> order: the* zeroth element of this array is the most-significant int of the* magnitude.  The magnitude must be "minimal" in that the most-significant* int ({@code mag[0]}) must be non-zero.  This is necessary to* ensure that there is exactly one representation for each BigInteger* value.  Note that this implies that the BigInteger zero has a* zero-length mag array.*/final int[] mag;

signum表示正负

mag是一个多段的数组

先变成补码, 然后以32位为一组, 分成n组, 再转成10进制放到数组mag中

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

存储上限:

存储方式为: [1, -2147483648, 0]

数组中最大长度是int的最大值: 2147483647

数组中每一位能表示的数字: -2147483648 ~ 2147483647

也就是说数组中最多21亿个元素, 每个元素能表示的数字位42亿多

所以BigInteger能表示的最大数字为: 42亿的21亿次方

实际计算机不可能有这么大内存

BigDecimal

计算机中的小数

0.875 转为二进制 111

0.9 - 45位二进制

底层:

类型占用字节数总bit位数小数部分bit位数
float4个字节32bit23bit
double8个字节64bit52bit

所以有些小数在计算的时候会很不精确

BigDecima
构造
  1. 通过传递double类型的小数来创建对象, 这种方式有可能不精确, 不建议使用
  2. 通过传递字符串表示的小数来创建对象, 就会很精确
  3. 通过静态方法获取对象valueof

推荐使用方法2和方法3

package BigDecimalDemo;import java.math.BigDecimal;public class BigDecimalTest {public static void main(String[] args) {// 构造方法BigDecimal bd1 = new BigDecimal(0.01);BigDecimal bd2 = new BigDecimal(0.09);System.out.println(bd1);System.out.println(bd2);// 都不精确// 字符串传递BigDecimal bd3 = new BigDecimal("0.01");BigDecimal bd4 = new BigDecimal("0.09");System.out.println(bd3);System.out.println(bd4); // 精确BigDecimal bd5 = bd3.add(bd4);System.out.println(bd5); // 精确// 静态方法构造BigDecimal bd6 = BigDecimal.valueOf(0.1);System.out.println(bd6); //精确}
}

细节:

  1. 如果要表示的数字不大, 没有超出double的取值范围, 建议使用静态方法
  2. 如果要表示的书自己表达, 超出了double的取值范围,建议使用构造方法
  3. 如果传递的是0-10之间的整数, 包含0 包含10, 那么方法会返回已经创建好的对象, 不会重新new

验证代码:

BigDecimal bd6 = BigDecimal.valueOf(10);
BigDecimal bd7 = BigDecimal.valueOf(10);
System.out.println(bd6 == bd7); // trueBigDecimal bd8 = BigDecimal.valueOf(10.0);
BigDecimal bd9 = BigDecimal.valueOf(10.0);
System.out.println(bd8 == bd9); // false

解释: 只有当传递1-10之间的整数时, 是同一个对象, 但如果是小数, 都是new出来的

成员方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package BigDecimalDemo;import java.math.BigDecimal;
import java.math.RoundingMode;public class BigDecimalTest2 {public static void main(String[] args) {// 创建对象BigDecimal bd1 = BigDecimal.valueOf(10.0);BigDecimal bd2 = BigDecimal.valueOf(2.0);// 加法BigDecimal bd3 = bd1.add(bd2);System.out.println(bd3);// 减法BigDecimal bd4 = bd1.subtract(bd2);System.out.println(bd4);// 乘法BigDecimal bd5 = bd1.multiply(bd2);System.out.println(bd5);// 除法BigDecimal bd6 = bd1.divide(bd2);System.out.println(bd6);// 以上结果为: 12.0 8.0 20.00 5// 除法精确几位小数BigDecimal bd7 = bd1.divide(bd2, 5, RoundingMode.HALF_UP);// half_Up就是四舍五入System.out.println(bd7); //5.00000}
}

舍入模式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

UP: 远离0的方向舍入

DOWN: 向0的方向舍入

HALF_EVEN:

例子:with HALF_EVEN rounding 5.5 6, 2.5 2, 1.6 2, 1.1 1, 1.0 1, -1.0 -1, -1.1 -1, -1.6 -2, -2.5 -2, -5.5 -6,

BigDecimal底层存储模式

首先不管是静态方法还是字符串传入, 都是new出来的

首先会对字符串进行遍历, 然后把每个字符对应的ASCII码存入到数组中

debug调试:

package BigDecimalDemo;import java.math.BigDecimal;public class BigDecimalTest3 {public static void main(String[] args) {BigDecimal bd1 = BigDecimal.valueOf(0.226);BigDecimal bd2 = BigDecimal.valueOf(123.226);BigDecimal bd3 = BigDecimal.valueOf(-1.5);}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上限: 小数总长度不超过数组长度也就是INT_MAX

小结:

  1. BigDecimal作用: 表示较大的小数和纪珏小数精度失真问题
  2. BigDecimal的对象如何获取? 传入字符串, 静态方法valueof
  3. 常见操作: 加减乘除 (四舍五入: RoundingMode.HALF_UP)

6.正则表达式

一种校验字符串的规则

校验用户名, 密码等是否满足规则可以用到

作用:
  1. 校验字符串是否满足规则
  2. 在一段文本中查找满足要求的内容

使用规则

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

细节: 如果要求两个范围的交集, 写两个&&才行, 写成一个的话就会当成是判断是否是&符号

转义字符: \ 改变后面那个字符原本的含义

代码示例:

// 只能是a b c
System.out.println(“-----------1-------------”);
System.out.println(“a”.matches(“[abc]”)); // true
System.out.println(“z”.matches(“[abc]”)); // false

    // 不能出现a b cSystem.out.println("-----------2-------------");System.out.println("a".matches("[^abc]")); // falseSystem.out.println("z".matches("[^abc]")); // trueSystem.out.println("zz".matches("[^abc]")); //falseSystem.out.println("zz".matches("[^abc][^abc]")); //true// a到zA到Z(包括头尾的范围)System.out.println("-----------3-------------");System.out.println("a".matches("[a-zA-z]")); // trueSystem.out.println("z".matches("[a-zA-z]")); // trueSystem.out.println("aa".matches("[a-zA-z]"));//falseSystem.out.println("zz".matches("[a-zA-Z]")); //falseSystem.out.println("zz".matches("[a-zA-Z][a-zA-Z]")); //trueSystem.out.println("0".matches("[a-zA-Z]"));//falseSystem.out.println("0".matches("[a-zA-Z0-9]"));//true
    // [a-d[m-p]] a到d,或m到pSystem.out.println("-----------4-------------");System.out.println("a".matches("[a-d[m-p]]"));//trueSystem.out.println("d".matches("[a-d[m-p]]")); //trueSystem.out.println("m".matches("[a-d[m-p]]")); //trueSystem.out.println("p".matches("[a-d[m-p]]")); //trueSystem.out.println("e".matches("[a-d[m-p]]")); //falseSystem.out.println("0".matches("[a-d[m-p]]")); //false// [a-z&&[def]] a-z和def的交集。为:d,e,fSystem.out.println("----------5------------");System.out.println("a".matches("[a-z&[def]]")); //falseSystem.out.println("d".matches("[a-z&&[def]]")); //trueSystem.out.println("0".matches("[a-z&&[def]]")); //false// [a-z&&[^bc]] a-z和非bc的交集。(等同于[ad-z])System.out.println("-----------6------------_");System.out.println("a".matches("[a-z&&[^bc]]"));//trueSystem.out.println("b".matches("[a-z&&[^bc]]")); //falseSystem.out.println("0".matches("[a-z&&[^bc]]")); //false// [a-z&&[^m-p]] a到z和除了m到p的交集。(等同于[a-1q-z])System.out.println("-----------7-------------");System.out.println("a".matches("[a-z&&[^m-p]]")); //trueSystem.out.println("m".matches("[a-z&&[^m-p]]")); //falseSystem.out.println("0".matches("[a-z&&[^m-p]]")); //false

// \ 转义字符 改变后面那个字符原本的含义
//练习:以字符串的形式打印一个双引号
//"在Java中表示字符串的开头或者结尾

    //此时\表示转义字符,改变了后面那个双引号原本的含义//把他变成了一个普普通通的双引号而已。System.out.println("\"");// \表示转义字符//两个\的理解方式:前面的\是一个转义字符,改变了后面\原本的含义,把他变成一个普普通通的\而已。System.out.println("c:Users\\moon\\IdeaProjects\\basic-code\\myapi\\src\\com\\itheima\\a08regexdemo\\RegexDemo1.java");
    //.表示任意一个字符System.out.println("你".matches("..")); //falseSystem.out.println("你".matches(".")); //trueSystem.out.println("你a".matches(".."));//true// \\d 表示任意的一个数字// \\d只能是任意的一位数字// 简单来记:两个\表示一个\System.out.println("a".matches("\\d")); // falseSystem.out.println("3".matches("\\d")); // trueSystem.out.println("333".matches("\\d")); // false//\\w只能是一位单词字符[a-zA-Z_0-9]System.out.println("z".matches("\\w")); // trueSystem.out.println("2".matches("\\w")); // trueSystem.out.println("21".matches("\\w")); // falseSystem.out.println("你".matches("\\w"));//false// 非单词字符System.out.println("你".matches("\\W")); // trueSystem.out.println("---------------------------------------------");// 以上正则匹配只能校验单个字符。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码示例:

    // 必须是数字 字母 下划线 至少 6位System.out.println("2442fsfsf".matches("\\w{6,}"));//trueSystem.out.println("244f".matches("\\w{6,}"));//false// 必须是数字和字符 必须是4位System.out.println("23dF".matches("[a-zA-Z0-9]{4}"));//trueSystem.out.println("23 F".matches("[a-zA-Z0-9]{4}"));//falseSystem.out.println("23dF".matches("[\\w&&[^_]]{4}"));//trueSystem.out.println("23_F".matches("[\\w&&[^_]]{4}"));//false

练习

验证手机号:

分成三部分:

  1. 1 表示手机号码只能以1开头
  2. [3-9] 表示第二位数字必须是3-9之间的
  3. \\d{9} 表示任意数字可以出现9次, 也只能出现9次
package RegexDemo;public class RegexDemo2 {public static void main(String[] args) {// 验证手机号码String regex1 = "1[3-9]\\d{9}";System.out.println("13112345678".matches(regex1));System.out.println("131123_5678".matches(regex1));System.out.println("1311a345678".matches(regex1));System.out.println("131152345678".matches(regex1));System.out.println("03112345678".matches(regex1));}
}
座机号码三部分
  1. 区号 0\\d{2,3}
  2. -? 表示0次或1次
  3. 号码的第一位也不能以0开头, 总长度5-10
验证邮箱
//         验证邮箱
//         1. @ 左边 任意字母数字下划线至少一次
//         2. @有且仅有一次
//         3. @ 右边
//         3.1  . 的左边  任意字母加数字2-6次, 且不能有下划线
//         3.2  \\.
//         3.3 大写小写字母都可 2-3次
//         3.4 3.3部分可以出现1-2次String regex3 = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";System.out.println("474328774@qq.com".matches(regex3));

扩展:

平时几乎不用自己写, 下载插件any-rule, 在双引号中间右键, 然后点击any-rule可以查到很多模板

我们需要先看懂, 再根据自己的要求进行修改

验证身份证
package RegexDemo;public class RegexDemo3 {public static void main(String[] args) {
//        请编写正则表达式验证用户名是否满足要求。
//        要求:大小写字母,数字,下划线一共4-16位String regex1 = "\\w{4,16}";//        请编写正则表达式验证身份证号码是否满足要求。
//        简单要求:18位,前17位任意数字,最后一位可以是数字可以是大写或小写的X
//        复杂要求:按照身份证号码的格式严格要求String regex2 = "[0-9]{17}(0-9|X|x)";String regex3 = "[0-9]{17}[\\dXx]";String regex7 = "[0-9]{17}(\\d|(?i)x";// regex2 和regex3 和 regex7等价System.out.println("76104310000564371x".matches(regex2));// 忽略大小写的书写方式// 在匹配的时候忽略abc的大小写String regex4 = "(?i)abc";// 之忽略bc的大小写String regex5 = "a(?i)bc";
//      只忽略b的大小写String regex6 = "a((?i)b)c";System.out.println("abc".matches(regex6));System.out.println("aBc".matches(regex6));// 复杂String IDCardRegex = "[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|10|11|12)(0[1-9]|[1-2]\\d|30|31)\\d{3}[\\dXx]";}
}

小结:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作用2 在一段文本中查找满足作用的内容

爬虫

Pattern: 表示正则表达式

Matcher: 文本匹配器, 作用: 按照正则表达式的规则去读取字串, 从头开始读取

package RegexDemo1;import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexTest {public static void main(String[] args) {// 要求找出里面所有的JAVAXXString str = "Java自从95年问世以来, 经历了很多版本, 目前企业中用的最多的是Java8" + "和Java11, 因为这两个是长期支持版本, 下一个长期支持版本是Java17, 相信在未来不久Java17也会登上历史舞台";// 获取正则表达式的对象Pattern p = Pattern.compile("Java\\d{0,2}");// 获取文本匹配器的对象// m: 文本匹配器的对象// str: 大串// p: 规则// 理解为: m要在str中找符合p规则的小串Matcher m = p.matcher(str);// 拿着文本匹配器从头开始读取, 寻找是否有满足规则的子串// 如果没有, 方法返回false// 如果有, 返回true, 在底层记录字串的起始索引和结束索引+1// 0, 4boolean b = m.find();System.out.println(b); // true// 方法底层会根据find方法记录的索引进行字符串的截取// subString(start, end) 包头不包围// (0, 4) 但是不包括4索引// 会把街区的小串进行返回String s1 = m.group();System.out.println(s1);// 第二次调用find的时候, 会继续读取后面的内容// 重复返回while(m.find()){s1 = m.group();System.out.println(s1);}}
}

练习:

package RegexDemo1;import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexTest2 {public static void main(String[] args) {String str = "来黑马程序员学习Java" +"电话: 18512516758,18512508907" +"或者联系邮箱: boniu@itcast.cn," +"座机电话:01036517895,010-98951256"+"邮箱: bozai@itcast.cn" +"热线电话: 400-618-9090,400-618-4000,4006184000,4006189090";// 把电话, 邮箱, 手机号, 热线都爬取出来String phone = "1[3-9]\\d{9}";String mail = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";String zuoJi = "0\\d{2,3}-?[1-9]\\d{4,9}";String reXian = "400-?[1-9]\\d{2}-?[1-9]\\d{3}";String regex = "(1[3-9]\\d{9})|" +"(\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2})|" +"(0\\d{2,3}-?[1-9]\\d{4,9})|" +"(400-?[1-9]\\d{2}-?[1-9]\\d{3})";// 获取正则表达式对象Pattern p = Pattern.compile(regex);// 获取文本匹配器的对象Matcher m = p.matcher(str);while (m.find()){String s = m.group();System.out.println(s);}}
}
有条件的数据爬取

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

需求1:

package RegexDemo1;import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexTest3 {public static void main(String[] args) {String str = "Java自从95年问世以来, 经历了很多版本, 目前企业中用的最多的是Java8" +"和Java11, 因为这两个是长期支持版本, 下一个长期支持版本是Java17, " +"相信在未来不久Java17也会登上历史舞台";// 1.定义正则表达式// ?理解为前面的数据Java// =表示在Java后面要跟随的数据// 但是在获取的时候, 只获取前半部分String regex = "Java(?=8|11|17)";Pattern p = Pattern.compile(regex);Matcher m = p.matcher(str);while (m.find()){String s = m.group();System.out.println(s);}}
}

需求2:

// 需求2
String regex2 = "Java(8|11|17)";
String regex3 = "Java(?:8|11|17)"; // 都可以Pattern p = Pattern.compile(regex3);
Matcher m = p.matcher(str);
while (m.find()){String s = m.group();System.out.println(s);
}

需求3:

// 需求3
String regex4 = "Java(?!8|11|17)";
Pattern p = Pattern.compile(regex4);
Matcher m = p.matcher(str);
while (m.find()){String s = m.group();System.out.println(s);
}

小结:

带有选择性的数据爬取

String regex1 = "Java(?=8|11|17)";

获取的时候只获取前半部分

String regex3 = "Java(?:8|11|17)";

全都获取

String regex4 = "Java(?!8|11|17)";

只要Java, 不爬取Java8, 11, 17

贪婪爬取和非贪婪爬取

贪婪爬取: 在爬取数据的时候, 尽可能的多获取 abbbbbbbbbbbbbbb

非贪婪爬取: 尽可能少获取 ab

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Java默认贪婪爬取

如果我们在数量词 + * 的后面加上问号, 就是非贪婪爬取

package RegexDemo1;import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexTest4 {public static void main(String[] args) {String s = "Java自从95年问世以来," +"abbbbbbbbbbbbaaaaaaaaaaaaaaaaaa经历了很多版本," +"目前企业中用的最多的是Java8和Java11," +"因为这两个是长期支持版本," +"下一个长期支持版本是Java17," +"相信在未来不久Java17也会逐渐登上历史舞台";String regex1 = "ab+";Pattern p = Pattern.compile(regex1);Matcher m = p.matcher(s);while (m.find()){String str = m.group();System.out.println(str); // abbbbbbbbbbb}String regex2 = "ab+?";p = Pattern.compile(regex2);m = p.matcher(s);while (m.find()){String str = m.group();System.out.println(str); // ab}}
}
正则表达式在字符串方法中的使用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

replaceAll 细节:

方法在底层跟之前一样也会创建文本解析器的对象

然后从头开始去读取字符串中的内容, 只要有满足的, 那么就用第二个参数去替换

package RegexDemo;public class RegexDemo4 {public static void main(String[] args) {// replacaAll 和 split 应用String s = "消失时bfdcjhsbj456小蛋蛋fbgdsyue458小灰灰";// 把三个名字之间的字母替换为vsString res = s.replaceAll("[\\w&&[^_]]+", "vs");System.out.println(res); // 消失时vs小蛋蛋vs小灰灰// 把字符串中的三个姓名切割出来String[] arr = s.split("[\\w&&[^_]]+");for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}
//        消失时
//        小蛋蛋
//        小灰灰}
}

想知道字符串哪些识别正则表达式, 可以看这个方法的参数是否有regex, 有regex的方法就可以识别正则表达式

分组

概述

分组就是个小括号

每组是有组号的, 也就是序号

规则1: 从1开始, 连续不间断

规则2: 以左括号为基准, 最左边的是第一组, 其次为第二组, 以此类推

练习: 捕获分组

捕获分组就是把这一组的数据捕获出来,再用一次

需求1:判断一个字符串的开始字符和结束字符是否一致?

只考虑一个字符

举例: a123a b456b 17891 &abc&

需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符

举例:abc123abc b456b 123789123 &!@abc&!@

需求3:判断一个字符串的开始部分和结束部分是否一致? 开始部分内部每个字符也需要一致

举例:bbb456bbb 111789111 &&abc&& aaa123aaa

package RegexDemo;public class RegexDemo5 {public static void main(String[] args) {// 需求1: 判断开头结尾是否一致, 只考虑一个字符//   \\组号: 表示把第X组的内容拿出来在用一次String regex1 = "(.).+\\1";System.out.println("a123a".matches(regex1));System.out.println("b456b".matches(regex1));System.out.println("17891".matches(regex1));System.out.println("&abc&".matches(regex1));System.out.println("&745*".matches(regex1)); // false// 需求2: 判断开头结尾是否一致, 可以有多个字符String regex2 = "(.+).+\\1";System.out.println("abc123abc".matches(regex2));// 需求3: 开始部分内部每个字符要一致// (.) 把首字母看作一组// \\2 把首字母拿出来再次使用//  * 作用于\\2, 表示后面重复的内容出现0次或多次String regex3 = "((.)\\2*).+\\1";System.out.println("bbb456bbb".matches(regex3));System.out.println("111789111".matches(regex3));System.out.println("aaa123aaa".matches(regex3));System.out.println("aaa123aab".matches(regex3));}
}

捕获分组

正则内部使用: \\组号

正则外部使用: $组号


需求: 将字符串: 我要学学编编编编编编程程程程程程

替换为: 我要学编程

package RegexDemo;public class RegexDemo6 {public static void main(String[] args) {
//        需求: 将字符串: 我要学学编编编编编编程程程程程程
//        替换为: 我要学编程String s = "我要学学编编编编编编程程程程程程";// (.) 把重复内容的第一个字符 看作一组// \\1 表示第一个字符再次出现//  + 至少一次// $1 表示正则表达式中第一组的内容String res1 = s.replaceAll("(.)\\1+", "$1");System.out.println(res1);}
}
非捕获分组

分组之后不需要再用本组数据, 仅仅是把数据括起来

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不占用组号, 再写\\1就会报错

更多使用第一个

?: 可以不写, 但是一般都用, 要能看懂

7.时间相关类

7.1 JDK7前的时间相关类

Date 时间

SimpleDateFormat 格式化时间

Calendar 日历

时间相关知识

全世界的时间有一个统一的标准

格林尼治时间(Greenwich Mean Time) 简称GMT

计算核心: 地球自转一天是24小时, 太阳直射时为正午12点

但是这种方法误差太大(最大16分钟)

2012年后使用原子钟

原理: 利用铯原子的振动频率计算出来的时间, 作为世界标准时间(UTC). 每秒震动91亿次

1s = 1000ms = 1 000 000 微秒 = 1 000 000 000 纳秒

Date类

Date类是一个JDK写好的JavaBean类, 用来描述时间, 精确到毫秒

利用空参构造创建的对象, 默认表示系统当前时间

利用有参构造创建的对象, 表示指定的时间

修改事件对象的毫秒值

setTime(毫秒值)

获取时间对象中的毫秒值

getTime();

package DateDemo;import java.util.Date;public class DateDemo1 {public static void main(String[] args) {// 1. 创建对象表示一个时间Date d1 = new Date();System.out.println(d1);// 2. 创建对象, 表示指定时间Date d2 = new Date(0L);System.out.println(d2);// 3. setTime 修改时间d2.setTime(1000L);System.out.println(d2);// 4. getTime 获取当前时间的毫秒值long time = d2.getTime();System.out.println(time);}
}

练习:

package DateDemo;import java.util.Date;
import java.util.Random;public class DateDemo2 {public static void main(String[] args) {// 需求1: 打印时间原点开始一年之后的时间// 需求2: 定义两个Date对象,比较一下那个时间在前, 那个在后//extracted();// 2Random r = new Random();Date d1 = new Date(Math.abs(r.nextInt()));Date d2 = new Date(Math.abs(r.nextInt()));System.out.println(d1);System.out.println(d2);long time1 = d1.getTime();long time2 = d2.getTime();if(time1 > time2){System.out.println("d1在后");} else if (time1 < time2) {System.out.println("d2在后");}else {System.out.println("时间相等");}}private static void extracted() {// 需求1Date d1 = new Date(0L);long time = d1.getTime();time += 1000L * 3600 * 24 * 365;System.out.println(time);d1.setTime(time);System.out.println(d1);}
}
SimpleDateFormat
作用:

格式化: 把时间变成喜欢的格式

解析: 把字符串表示的时间变成Date对象(2022年1月1日转为Date时间)

常用方法:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有参构造中的参数 的模式对应关系

yyyy-MM-dd HH:mm:ss

yyyy年MM月dd日 HH:mm:ss EE

package SimpleDateFormat;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class SimpleDateFormatDemo1 {public static void main(String[] args) throws ParseException {extracted();// 定义一个字符串表示时间String str = "2023-11-15 19:51:00";// 利用空参构造创建SimpleDateFormat对象// 细节:// 创建对象的格式要跟字符串的格式完全一致SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date date = sdf.parse(str);System.out.println(date.getTime()); // 得到一个Date对象}private static void extracted() {// 利用空参构造创建对象SimpleDateFormat sdf1 = new SimpleDateFormat();Date d1 = new Date(0L);String str1 = sdf1.format(d1);System.out.println(str1); //1970/1/1 08:00// 利用带参构造 指定格式输出SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss EE");String str2 = sdf2.format(d1);System.out.println(str2); // 1970-00-01 08:00:00 周四}
}
练习

把2000-11-11转换为2000年11月11日

package SimpleDateFormat;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class Demo2 {public static void main(String[] args) throws ParseException {String str = "2000-11-11";SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");Date date = sdf1.parse(str); //System.out.println(date);SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日");String res = sdf2.format(date);System.out.println(res);}
}
Calendar
概述

Calendar代表了系统当前时间的日历对象, 可以单独修改, 获取事件中的年月日

细节: Calendar是一个抽象类, 不能直接创建对象

获取Calendar对象的方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

常用方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package CalenDarDemo;import java.util.Calendar;
import java.util.Date;public class Demo1 {public static void main(String[] args) {// 1. 获取日历对象// 细节1: Calendar是一个抽象类, 不能直接new, 而是通过一个静态方法获取子类对象// 底层原理:// 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间// 会把事件中的纪元, 年, 月, 日, 时分秒星期等都放到一个数组中// 细节2:// 月份: 范围0-11 依次表示1-12月// 星期: 在老外的眼里, 1代表星期日, 以此类推Calendar c = Calendar.getInstance();System.out.println(c);// 修改日历代表的时间// 0 - 纪元// 1 - 年// 2 -月// 3 - 一年的中的第几周// 4 - 一个月中的第几周// 5 - 一个月中的第几天(日期)Date d = new Date(0L);c.setTime(d);System.out.println(c);// java在Calender类中, 把索引dui'yint year = c.get(Calendar.YEAR);int month = c.get(Calendar.MONTH);int date = c.get(Calendar.DAY_OF_MONTH);int week = c.get(Calendar.DAY_OF_WEEK);System.out.println(year + ", " + month + ", " + date + ", " + week); // 1970, 0, 1, 5// 获取毫秒值c.setTimeInMillis(1000);long timeInMillis = c.getTimeInMillis();System.out.println(timeInMillis);c.set(Calendar.YEAR, 1997);c.set(Calendar.MONTH, 4);// 在1号的基础加7天c.add(Calendar.DAY_OF_MONTH, 7);year = c.get(Calendar.YEAR);month = c.get(Calendar.MONTH);date = c.get(Calendar.DAY_OF_MONTH);week = c.get(Calendar.DAY_OF_WEEK);System.out.println(year + ", " + month + ", " + date + ", " + week); //1997, 4, 8, 5}
}

7.2 JDK8新增时间相关类

JDK7 和 JDK8 时间相关类的区别

代码层面 安全层面

JDK7 代码麻烦 JDK7多线程下会导致数据安全的问题

JDK8 简单 时间日期对象都是不可变的, 解决了这个问题

要学习的类

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Date类
ZoneId时区
常用方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package ZoneIdDemo;import java.time.ZoneId;
import java.util.Set;public class Demo1 {public static void main(String[] args) {// 获取Java中所有时区Set<String> s = ZoneId.getAvailableZoneIds();System.out.println(s);// 获取系统默认时区ZoneId zoneId = ZoneId.systemDefault();System.out.println(zoneId);// 获取指定时区ZoneId newYork = ZoneId.of("America/Cuiaba");System.out.println(newYork);}
}
Instant时间戳
常见方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package ZoneIdDemo;import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;public class Demo2 {public static void main(String[] args) {// 获取当前时间的Instant对象Instant now = Instant.now();System.out.println(now); //2023-11-16T02:28:07.829588600Z// 根据(秒 毫秒 纳秒)获取Instant对象Instant instant1 = Instant.ofEpochSecond(0L);System.out.println(instant1); //1970-01-01T00:00:00ZInstant instant2 = Instant.ofEpochSecond(1L);System.out.println(instant2); // 1970-01-01T00:00:01ZInstant instant3 = Instant.ofEpochSecond(1L, 1000000000L);System.out.println(instant3); // 1970-01-01T00:00:02Z// 指定时区ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));System.out.println(time); // 2023-11-16T10:30:36.375789800+08:00[Asia/Shanghai]// 判断 isXxxInstant instant4 = Instant.ofEpochMilli(0L);Instant instant5 = Instant.ofEpochMilli(1000L);// isBefore: 判断调用者时间是否在参数表示的时间前面// isAfter: 判断调用者时间是否在参数表示的时间后面boolean res1 = instant4.isBefore(instant5);boolean res2 = instant4.isAfter(instant5);System.out.println(res1 + " " + res2); // true false// 时间增加或减少的方法Instant instant6 = Instant.ofEpochMilli(3000L);Instant instant7 = instant6.minusSeconds(1);System.out.println(instant6); // 1970-01-01T00:00:03ZSystem.out.println(instant7); // 1970-01-01T00:00:02Z}
}
ZoneDateTime
常用方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package ZoneIdDemo;import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;public class Demo3 {public static void main(String[] args) {// 获取当前时间对象(带时区ZonedDateTime now = ZonedDateTime.now();System.out.println(now); // 2023-11-16T10:48:57.839325100+08:00[Asia/Shanghai]// 获取指定那个的时间对象(带时区// 年月日时分秒纳秒指定ZonedDateTime time1 = ZonedDateTime.of(2023,11,16,10,51,0,0,ZoneId.of("Asia/Shanghai"));System.out.println(time1); // 2023-11-16T10:51+08:00[Asia/Shanghai]// 通过Instant + 时区的方式指定获取的时间对象Instant instant = Instant.ofEpochMilli(0L);ZoneId zoneId = ZoneId.of("Asia/Shanghai");ZonedDateTime time2 = ZonedDateTime.ofInstant(instant, zoneId);System.out.println(time2); // 1970-01-01T08:00+08:00[Asia/Shanghai]// withXxx 修改时间系列的方法ZonedDateTime time3 = time2.withYear(2020);System.out.println(time3); // 2020-01-01T08:00+08:00[Asia/Shanghai]// 减少时间ZonedDateTime time4 = time3.minusHours(1);System.out.println(time4); // 2020-01-01T07:00+08:00[Asia/Shanghai]// 增加时间ZonedDateTime time5 = time4.plusDays(30);System.out.println(time5); // 2020-01-31T07:00+08:00[Asia/Shanghai]}
}
日期格式化类
DateTimeFormatter

用于时间的格式化和解析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package ZoneIdDemo;import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;public class Demo4 {public static void main(String[] args) {// 获取时间对象ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));// 解析/格式化器DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EE a");// 格式化String res = dtf1.format(time);System.out.println(res); // 2023-11-16 11:04:06 周四 上午}
}
日历类(Calendar)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LocalDate

年月日

package ZoneIdDemo;import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Month;public class Demo5 {public static void main(String[] args) {// 1.获取当前时间的日历对象 年月日LocalDate nowDate = LocalDate.now();System.out.println(nowDate); // 2023-11-16// 2.获取指定时间的日历对象LocalDate date1 = LocalDate.of(2000, 1, 1);System.out.println(date1); // 2000-01-01// 3.get系列方法获取日历中的每一个属性值// 获取月有两种方式int year = date1.getYear();Month month = date1.getMonth();System.out.println(month); // JANUARYint monthValue = date1.getMonthValue();int dayOfMonth = date1.getDayOfMonth();System.out.println(year + "-" + monthValue + "-" + dayOfMonth); // 2000-1-1// 判断日期前后LocalDate date2 = LocalDate.of(2023,11,16);boolean res1 = date1.isBefore(date2);System.out.println(res1); // trueboolean res2 = date1.isAfter(date2);System.out.println(res2); // false// with修改时间LocalDate date3 = date2.withYear(2020);System.out.println(date3); // 2020-11-16, 也就是说只修改了年份, 月份日期都不变// minus 减少 plus增加时间LocalDate date4 = date3.minusMonths(1);System.out.println(date4); // 2020-10-16LocalDate date5 = date3.plusDays(1);System.out.println(date5); // 2020-11-17}}
LocalTime

时分秒

LocalDateTime

年月日 时分秒

LocalDateTime还能转换为其他两者

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

工具类
Duration

用于计算两个时间间隔(秒 纳秒)

package ZoneIdDemo;import java.time.Duration;
import java.time.LocalDateTime;public class DurationDemo {public static void main(String[] args) {// 现在的时间LocalDateTime today = LocalDateTime.now();System.out.println(today); // 2023-11-16T14:59:17.564971100LocalDateTime birthday = LocalDateTime.of(1997,4,8,0,0);System.out.println(birthday); // 1997-04-08T00:00Duration time = Duration.between(today, birthday);System.out.println(time); // PT-233247H-37.1452772SSystem.out.println("------------------------------------");System.out.println(time.toDays());System.out.println(time.toHours());System.out.println(time.toMinutes());System.out.println(time.toMillis());System.out.println(time.toNanos());
//        -9718
//        -233247
//        -13994822
//        -839689361893
//        -839689361893931200}
}
Period

用于计算两个日期间隔(年月日)

package ZoneIdDemo;import java.time.LocalDate;
import java.time.Period;public class PeriodDemo {public static void main(String[] args) {// 当前时间的年月日LocalDate today = LocalDate.now();System.out.println(today); // 2023-11-16// 之前的一个时间LocalDate birthday = LocalDate.of(1997,4,8);System.out.println(birthday); // 1997-04-08Period period = Period.between(today, birthday);System.out.println(period); //P-26Y-7M-8DSystem.out.println(period.getYears()); // -26System.out.println(period.getMonths()); // -7System.out.println(period.getDays()); // -8}
}
ChronoUnit

用于计算两个日期间隔, 全面

package ZoneIdDemo;import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.TooManyListenersException;public class ChronoUnitDemo {public static void main(String[] args) {// 当前时间LocalDateTime now = LocalDateTime.now();// 生日时间LocalDateTime birth = LocalDateTime.of(1997,4,8,0,0,0);System.out.println("相差的年数: " + ChronoUnit.YEARS.between(birth, now));System.out.println("相差的月数: " + ChronoUnit.MONTHS.between(birth, now));System.out.println("相差的周数: " + ChronoUnit.WEEKS.between(birth, now));System.out.println("相差的天数: " + ChronoUnit.DAYS.between(birth, now));System.out.println("相差的时数: " + ChronoUnit.HOURS.between(birth, now));System.out.println("相差的分数: " + ChronoUnit.MINUTES.between(birth, now));System.out.println("相差的秒数: " + ChronoUnit.SECONDS.between(birth, now));System.out.println("相差的毫秒数: " + ChronoUnit.MILLIS.between(birth, now));System.out.println("相差的微秒数: " + ChronoUnit.MICROS.between(birth, now));System.out.println("相差的纳秒数: " + ChronoUnit.NANOS.between(birth, now));System.out.println("相差的半天数: " + ChronoUnit.HALF_DAYS.between(birth, now));System.out.println("相差的十年数: " + ChronoUnit.DECADES.between(birth, now));System.out.println("相差的世纪数: " + ChronoUnit.CENTURIES.between(birth, now));System.out.println("相差的千年数: " + ChronoUnit.MILLENNIA.between(birth, now));System.out.println("相差的纪元数: " + ChronoUnit.ERAS.between(birth, now));}
}

8.包装类

包装类: 基本数据类型对应的引用数据类型

如何理解包装类:

用一个对象, 把基本数据类型给包起来

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8种包装类

  1. byte: Byte
  2. short: Short
  3. int: Integer
  4. long: Long
  5. float: Float
  6. double: Double
  7. char: Character
  8. boolean: Boolean

构造方法获取Integer对象和静态方法获取Integer对象的区别

二者都是JDK5以前的方法, 现在已经不用了, 但是需要知道区别

package BaoZhuangDemo;public class IntegerDemo {public static void main(String[] args) {// 静态方法获取Integer对象// 传入的数据在-128 ~ 127 之间// 会把提前擦创建好的对象提供出来, 不会创建新的, 可以节约内存// 否则会创建新的对象, 地址值就不一样了Integer i1 = Integer.valueOf(127);Integer i2 = Integer.valueOf(127);System.out.println(i1 == i2); // trueInteger i3 = Integer.valueOf(128);Integer i4 = Integer.valueOf(128);System.out.println(i3 == i4); // false// new关键字在Java中每次都是创建了一个新的对象// 所以两个new出来的对象地址一定是不一样的// 构造方法获取Integeri对象Integer i5 = new Integer(127);Integer i6 = new Integer(127);System.out.println(i5 == i6); // falseInteger i7 = new Integer(128);Integer i8 = new Integer(128);System.out.println(i7 == i8); // false}
}

以前的包装类如何相加?

  1. 把对象进行拆箱
  2. 相加
  3. 把得到的结果进行装箱

但是很麻烦

自动装箱和自动拆箱

JDK5的时候提出自动装箱和自动拆箱

自动装箱: 把基本数据类型自动变为其对应的包装类

自动拆箱: 把包装类自动变成其对象的基本数据类型

// 在底层, 此时还会去自动调用静态方法valueof得到一个Integer对象, 只不过这个动作不需要我们自己去操作
// 自动装箱的动作
Integer i = 10;Integer ii = new Integer(12);
// 自动拆箱的动作
i = ii;

在JDK5以后, int和Integer可以看作是同一个东西, 因为在内部可以自动转化

以后也会经常使用自动装箱的方式来获取包装类对象

Integer成员方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前三种方法都是返回字符串的原因:

  1. 二进制可能是0开头
  2. int类型有长度限制
方法演示
package BaoZhuangDemo;public class IntegerDemo2 {public static void main(String[] args) {// 1.把整数转为二进制 八进制 十六进制String str1 = Integer.toBinaryString(100);System.out.println(str1); // 1100100String str2 = Integer.toOctalString(100);System.out.println(str2); // 144String str3 = Integer.toHexString(100);System.out.println(str3); // 64// 2. 将字符串种类型的证书转为int类型的整数// Java是一种强类型语言, 每种数据都有各自的数据类型// 在计算的时候, 入股不是同一种数据类型, 是无法直接计算的int i = Integer.parseInt("123");System.out.println(i + 1); // 124// 细节1:// 在类型转换的时候, 括号中的参数只能是数字不能是其他的, 否则会报错// 细节2:// 8种包装类中, 除了Character都有对应的parseXxx的方法, 进行类型转换String str = "true";boolean b = Boolean.parseBoolean(str);System.out.println(b); // true}
}
键盘录入
package BaoZhuangDemo;import java.util.Scanner;public class IntegerDemo3 {public static void main(String[] args) {// 键盘录入Scanner sc = new Scanner(System.in);System.out.println("请输入一个字符串:");// 弊端:// 当我们在使用next,nextInt,nextDouble在接收数据的时候,// 遇到空格,回车,制表符的时候就停止了// 键盘录入的是123 123 那么此时只能接收到空格前面的数据// 我想要的是接收一整行数据// 约定:// 以后我们如果想要键盘录入,不管什么类型,统一使用nextLine// 特点遇到回车才停止String line = sc.nextLine();System.out.println(line);// 然后再利用parse方法转换int i = Integer.parseInt(line);System.out.println(i);}
}

练习题

package Practice;import java.util.ArrayList;
import java.util.Scanner;public class Practice1 {public static void main(String[] args) {
//        test01();test02();}// 及那盘录入一些1-100之间的整数, 并添加到集合中// 直到集合中所有数据和超过200为止public static void test01(){Scanner sc = new Scanner(System.in);ArrayList<Integer> list = new ArrayList<>();while(!moreThan200(list)){System.out.println("请输入1-200之间的整数: ");String s = sc.nextLine();int num = Integer.parseInt(s);list.add(num);}System.out.println("总和已超过200");}public static boolean moreThan200(ArrayList<Integer> list){int res = 0;for (int i = 0; i < list.size(); i++) {res += list.get(i);}return res > 200;}public static void test02(){String str = "23658105";// 校验字符串if(!str.matches("[1-9]\\d{0,9}]")){System.out.println("错误的数据");return;}int sum = 0;for (int i = 0; i < str.length(); ++i) {char c = str.charAt(i);int num = c - '0';sum = sum * 10 + num;}System.out.println(sum);}
}
package Practice;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;public class Practice2 {public static void main(String[] args) throws ParseException {String s1 = tenTo2(123);System.out.println(s1);// 验证String s2 = Integer.toBinaryString(123);System.out.println(s2);test02();System.out.println(isLeapYear(2000)); // trueSystem.out.println(isLeapYear(2001)); // false}public static String tenTo2(int num){// 将十进制整数转成字符串表示的二进制StringBuilder sb = new StringBuilder();while(num > 0){int x = num % 2;num /= 2;sb.insert(0, x);}return sb.toString();}public static void test02() throws ParseException {// 用代码计算活了多少天// JDK7String bir = "1997-04-08";SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Date date = sdf.parse(bir);// 获取生日的毫秒值long time1 = date.getTime();//System.out.println(time1);// 获取当前的毫秒值long time2 = System.currentTimeMillis();//System.out.println(time2);// 求差值long time = time2 - time1;System.out.println(time / 1000 / 3600 / 24);// JDK8LocalDate d1 = LocalDate.now();LocalDate d2 = LocalDate.of(1997, 4, 8);long days = ChronoUnit.DAYS.between(d2, d1);System.out.println(days);}// 判断是否为闰年public static boolean isLeapYear(int year){LocalDate d1 = LocalDate.of(year, 2, 1);LocalDate d2 = LocalDate.of(year, 3, 1);//return ChronoUnit.DAYS.between(d1, d2) == 29;// 还有一个专门的函数return d1.isLeapYear();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/189440.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习第8天:线性SVM分类

文章目录 介绍 特征缩放 示例代码 硬间隔与软间隔分类 主要代码 代码解释 结语 介绍 作用&#xff1a;判别种类 原理&#xff1a;找出一个决策边界&#xff0c;判断数据所处区域来识别种类 简单介绍一下SVM分类的思想&#xff0c;我们看下面这张图&#xff0c;两种分类都…

基于R语言平台Biomod2模型的物种分布建模与可视化分析

!](https://img-blog.csdnimg.cn/84e1cc8c7f9b4b6ab60903ffa17d82f0.jpeg#pic_center)

接口测试 —— 接口测试的意义

1、接口测试的意义&#xff08;优势&#xff09; &#xff08;1&#xff09;更早的发现问题&#xff1a; 不少的测试资料中强调&#xff0c;测试应该更早的介入到项目开发中&#xff0c;因为越早的发现bug&#xff0c;修复的成本越低。 然而功能测试必须要等到系统提供可测试…

前端uniapp列表下拉到底部加载下一页列表【下拉加载页面/带源码/实战】

目录 一. 图片1.2. 二.list.vue三.uni-load-more.vue最后 一. 图片 1. 2. 二.list.vue <template><view><!--列表--><scroll-view scroll-y"true" class"scroll-Y" :style"height: scrollviewHigh px;" lower-threshol…

股票价格预测 | Python实现基于CNN卷积神经网络的股票预测模型(keras,Conv1D)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 股票价格预测 | Python实现基于CNN卷积神经网络的股票预测模型(keras) 源码设计 import quandl import datetimedf = quandl

Jenkins自动化部署一个Maven项目

Jenkins自动化部署 提示&#xff1a;本教程基于CentOS Linux 7系统下进行 Jenkins的安装 1. 下载安装jdk11 官网下载地址&#xff1a;https://www.oracle.com/cn/java/technologies/javase/jdk11-archive-downloads.html 本文档教程选择的是jdk-11.0.20_linux-x64_bin.tar.g…

如何优化谷歌商店里应用的评分评论2

在做应用评分优化前&#xff0c;我们需要考虑用户以及他们如何在不浪费太多时间的情况下分享反馈。 1、及时妥善的回复评论。 许多潜在用户在决定下载应用之前都会查看评论。回复正面和负面评论&#xff0c;向用户表明我们重视他们的反馈。回复用户评论是一个改善应用公众形象…

AODNet

【20231117】读研期间没有对阅读的文章进行总结&#xff0c;没想到毕业反而有了机会。即日起会对阅读过的文章要点进行梳理记录&#xff0c;希望这一习惯能够坚持下去。 学术的角度&#xff1a;看论文要学习作者如何逻辑严谨的自证 落地的角度&#xff1a;只用看以下六点&#…

一个美观且功能丰富的 .NET 控制台应用程序开源库

推荐一个美观且功能丰富的 .NET 控制台应用程序开源库&#xff0c;从此告别黑漆漆的界面。 01 项目简介 Spectre.Console 是一个开源的 .NET 库&#xff0c;用于创建美观、功能丰富的控制台&#xff08;命令行&#xff09;应用程序。它提供了一组易于使用的 API&#xff0c;…

cocos----刚体

刚体&#xff08;Rigidbody&#xff09; 刚体&#xff08;Rigidbody&#xff09;是运动学&#xff08;Kinematic&#xff09;中的一个概念&#xff0c;指在运动中和受力作用后&#xff0c;形状和大小不变&#xff0c;而且内部各点的相对位置不变的物体。在 Unity3D 中&#xff…

C#WPF用户控件及自定义控件实例

本文演示C#WPF自定义控件实例 用户控件(UserControl)和自定义控件(CustomControl)都是对UI控件的一种封装方式,目的都是实现封装后控件的重用。 只不过各自封装的实现方式和使用的场景上存在差异。 1 基于UserControl 创建 创建控件最简单一个方法就是基于UserControl …

无线物理层安全大作业

这个标题很帅 Beamforming Optimization for Physical Layer Security in MISO Wireless NetworksProblem Stateme![在这里插入图片描述](https://img-blog.csdnimg.cn/58ebb0df787c4e23b0c7be4189ebc322.png) Beamforming Optimization for Physical Layer Security in MISO W…