java小白第二天

  • 00 写在前面
  • 01 面向对象
  • 01 类和对象
  • 类的相关总结
  • 02 就进原则和this
  • 03 构造方法
  • 04 对象内存图
  • 01 一个对象的内存图
  • 02 多个对象的内存图
  • 03 两个变量(引用)指向同一个对象的内存图
  • 04 this的内存原理
  • 05 基本数据类型和引用数据类型的区别
  • 06 局部变量和成员变量的区别
  • 03 面向对象的三大法宝
  • 01 封装
  • 01 private
  • 02 继承 -- 类与类中的父子关系
  • 01 子类到底能继承父类中的哪些内容
  • 02 继承中对象访问特点
  • 01 继承中成员变量访问特点
  • 02 继承中成员方法访问特点
  • 03 继承中构造方法访问特点
  • 03 多态
  • 01 多态调用成员的特点
  • 小结
  • 面向对象进阶
  • 01 static -- 共享
  • 01 static 静态对象(成员变量与成员方法)内存图
  • 02 小结
  • 02 认识main方法
  • 03 包
  • 04 final 关键字
  • 05 权限修饰符
  • 06 代码块
  • 01 局部代码块 -- 淘汰
  • 02 构造代码块 -- 淘汰
  • 03 静态代码块
  • 07 abstract
  • 08 interface
  • 01 接口的定义和使用
  • 02 接口中成员的特点
  • 03 接口和类之间的关系
  • 04 接口扩展
  • 01 jdk8开始接口中新增的方法
  • 02 接口应用
  • 03 3适配器设计模式
  • 09 内部类
  • 01 内部类分类
  • 10 浅克隆和深克隆
  • 11 转义字符
  • 11 正则表达式 Regex
  • 01 校验字符串
  • 02 爬虫
  • 03 正则表达式在字符串方法中的使用
  • 注意事项
  • 01 非捕获分组--代码示例
  • 02 分组 ()
  • API
  • 01 字符串
  • 01 String
  • 01 Stirng 方法
  • 02 StringBuilder
  • 01 构造方法
  • 02 常用方法
  • 03 StringJoiner
  • 01 构造方法
  • 02 成员方法
  • 04 字符串底层原理
  • 02 ArrayList--集合
  • 01 ArrayList
  • 03 System
  • 04 Runtime
  • 05 Object
  • 06 Objects
  • 07 BigInteger
  • 01 构造方法
  • 02 成员方法
  • 08 BigDecimal
  • 构造方法
  • 成员方法
  • 09 Date
  • 01 jdk7前时间相关类
  • 02 jdk8新增时间相关类
  • 01 ZoneID
  • 02 Instant 时间戳
  • 03 ZoneDateTime
  • 04 DateTimeFormatter
  • 05 LocalDate LocalTime LocalDateTime
  • 06 Duration Period ChronoUnit
  • 10 包装类
  • 10 Arrays
  • 插件
  • 案例 -- 拼图小游戏


00 写在前面

本文是边看黑马b站视频边写的一片笔记, 文中大多图片都来自黑马视频. 旨在巩固学习以及方便后续查阅和供广大朋友们学习, 感谢黑马视频分享

01 面向对象

内容目录架构

java 时间减去8小时_开发语言

01 类和对象

  • 类: 是对一类具有相似属性和行为的事物的抽象
  • 对象: 类的实例化, 具体的一个实体对象

都有什么类?

  1. javabean: 用来描述一类事物的类. (有成员变量, 方法等) 此类中不写main方法
  2. 测试类: 用来检查其他类是否书写正确, 带有main方法的类, 是程序的入口
  3. 工具类: 不是用来描述一类事物的, 而是帮我们做一些事情的类
  • 私有化构造方法
public class Tool{
     private Tool(){
     }
 }
  • 方法定义为静态

类定义格式

类的五大成员: 属性 方法 构造方法 代码块 内部类
public class 类名{
	1. 成员变量
	2. 静态变量
	3. 成员方法
	4. 静态方法
	5. 构造器
	6. 代码块
	7. 内部类
}
public class 类名{
	1. 成员变量
	数据类型 变量名;
	修饰符 数据类型 变量名 = 变量值;
	2 静态变量 -- 属于类的 所有实例化对象共享
	public static String school;
	3. 成员方法
	public 返回值类型 方法名(参数列表){
		方法体
		return 返回值;
	}
	4. 静态方法 -- 属于类的 所有实例化对象共享
	public static 返回值类型 方法名(参数列表){
		方法体
		return 返回值;
	}
	3. 构造器
	4. 代码块
	5. 内部类
}

# 一个标准类**javabean**要求
1. 所有成员变量都用 private 修饰
2. 提供私有成员变量的 getter 和 setter 方法
3. 提供空参和全参的构造方法
4. 提供 toString() 方法 -- 使得类的对象名的输出不是地址值, 而是属性值

创建对象格式
类名 对象名 = new 类名();

对象调用
对象名.成员变量;对象名.成员方法名();

note:

  1. 类名须是大驼峰命名格式
  2. 一个java文件中可以由多个类, 但只能有一个类被public修饰, 且文件名须和public修饰的类名一致
  3. 一般无需为成员变量赋值, 有默认值

数据类型

默认值

byte short int long

0

float double

0.0

char

" " 空格

boolean

false

String等引用类型

null

类的相关总结

这部分是对类涉及到的各方面零碎知识总结
成员修饰符

修饰符名称

作用

备注

private

private修饰的成员只能在类中被直接访问

类中成员变量都用private修饰,使用,结合get,set方法使用

public

所有对象都可访问

类中变量种类

  1. 成员变量
  2. 局部变量–方法中定义的变量

类中方法种类

  1. 成员方法
  2. 静态方法
  3. 构造方法–创建对象时给成员变量赋值

02 就进原则和this

就近原则 :类中的变量有成员变量和局部变量(方法中的变量),当两者同名时,谁离调用处近用谁

this : 区分成员变量和局部变量

03 构造方法

  • 创建对象时,虚拟机自动调用,初始化成员变量

构造方法格式

修饰符 类名(参数列表){
	方法体;
}

特点

  1. 方法名与类名相同
  2. 没有返回值类型
  3. 没有具体返回值–不能由 return 带回结果数据
  4. 创建对象时(new时),虚拟机自动调用
  5. 如果没有写构造方法,虚拟机自动添加一个空参构造方法
  6. 如果定义了构造方法,虚拟机将不会提供默认的空参构造方法

构造方法类型

1. 空参
public 类名(){
	...
} // 变量使用默认值
2. 全参
public 类名(需要赋值的成员变量列表){
	使用 this 关键字赋值
}

04 对象内存图

Java中jvm内存分配介绍

java 时间减去8小时_开发语言_02


字节码文件原来在方法区中, 现在在元空间中, 当运行一个类时, 就会加载其字节码文件到内存方法区, 栈内存, 堆内存存储内容如下:

方法区: 加载字节码文件进入内存

栈: 方法运行时进入的内存, 方法中创建的变量也在这里

堆: 凡是 new 出来的东西都在堆内存中, 并开辟相应空间产生地址标记

java 时间减去8小时_开发语言_03

01 一个对象的内存图

Student s = new Student();

创建上述一个对象时, 内存使用情况:

  1. 加载class文件–加载Student类的字节码文件
  2. 声明局部变量–s
  3. 在堆内存中开辟一个空间–new Student()
  4. 默认初始化
  5. 显示初始化
  6. 构造方法初始化
  7. 将堆内存中的地址值赋值给左边的局部变量



    当栈中所有方法执行完毕, 弹出栈后, 堆内存对应的空间就没有变量指向, 此时, 堆内存对应的空间也即变为垃圾空间, 内存空间被收回

    堆内存对应的空间也即变为垃圾空间, 内存空间被收回
02 多个对象的内存图

类的字节码文件只加载一次进内存

java 时间减去8小时_开发语言_04


java 时间减去8小时_java_05


java 时间减去8小时_父类_06


java 时间减去8小时_java 时间减去8小时_07

03 两个变量(引用)指向同一个对象的内存图

java 时间减去8小时_java 时间减去8小时_08


java 时间减去8小时_java_09

04 this的内存原理
  • this的本质: 代表方法调用者实例对象的地址值
  • this的作用: 区分局部变量和成员变量

this的内存图

java 时间减去8小时_父类_10

05 基本数据类型和引用数据类型的区别
  • 基本数据类型变量: 自己的空间中, 存储的是值
  • 引用数据类型变量: 自己的空间中, 存储的是地址引用, 即地址值
06 局部变量和成员变量的区别
  • 成员变量–类中方法外, 只要在类中方法外即可
  • 局部变量–方法中

图示如下

java 时间减去8小时_java_11

03 面向对象的三大法宝

封装 继承 多态

01 封装
  • 封装原则* 对象代表什么,就得封装对应的数据,并提供数据对应的行为
    如:人关门,关门的方法应该封装在门类中
01 private
  • private 权限修饰符
  • 用于修饰成员(成员方法和变量)
  • 被private修饰的成员只能在本类类中访问,即通过该类实例化的对象无法直接访问private修饰的成员
02 继承 – 类与类中的父子关系

减少代码冗余, 提高代码复用性

当类与类之间, 存在相同(共性)的内容, 并满足子类是父类中的一种, 就可以考虑使用继承, 来优化代码

java 时间减去8小时_jvm_12


01 继承格式:

public class Student extends Teacher{}

02 继承的特点

  1. java只支持单继承(一个类只能有一个直接父类), 不支持多继承, 但支持多层继承
  2. java中每一个类都直接或间接继承于 object 类
  3. 子类只能访问父类中非私有的成员
01 子类到底能继承父类中的哪些内容

父类中的内容大概分为三类如下:

构造方法

成员变量

成员方法

java 时间减去8小时_父类_13


进一步说明

java 时间减去8小时_java_14


01 构造方法不能被继承

子类不能继承父类构造方法

02 成员变量 – 子类可以继承父类中私有和非私有成员变量

创建的子类对象在堆内存中的空间被分为两块, 其中一块存储父类的所有成员变量(私有和非私有)

java 时间减去8小时_java 时间减去8小时_15


03 方法继承 – 子类可以继承父类中虚方法

java 为每个类创建一个对应的虚方法表, 每个类的虚方法表中包含来自父类的虚方法表中的方法

  • 虚方法表中的方法:
  1. 非 private
  2. 非 static
  3. 非 final

虚方法表 – 子类调用一个方法, 若是虚方法, 就去虚方法表中找, 提高效率. 此外, 若子类调用的方法不是虚方法, 子类会现在自己类中查找, 若没有, 则会一层一层向上查找

java 时间减去8小时_java_16


示例内存图

java 时间减去8小时_java 时间减去8小时_17

02 继承中对象访问特点
01 继承中成员变量访问特点

就近原则: 谁离我近, 我访问谁

访问顺序:

  1. 局部变量
  2. 成员变量 – 使用 this 关键字
  3. 父类成员变量 – 使用 super 关键字
  4. 都没有, 则逐级向上查找

示例图

java 时间减去8小时_jvm_18


java 时间减去8小时_父类_19

02 继承中成员方法访问特点

同样遵循就近原则

  • this: 从本类开始查找
  • super: 从父类开始查找

01 方法的重写

当父类的方法不能满足子类的需求时, 子类需要对父类方法进行重写

重写的本质: 使用子类中的方法替换从父类中继承的虚方法表中的方法

方法重写的对象: 具有继承关系的不同类之间的相同方法

方法的重载只与方法名和参数列表有关

02 书写格式

子类和父类中方法具有一摸一样的声明, 可以使用 @override 注解

03 方法重写的注意事项

  1. 重写方法的名称与形参列表必须与父类中的一致
  2. 子类重写父类的方法时, 访问权限必须大于等于父类 (public > protected > 没有权限修饰符 > private )
  3. 子类重写父类方法时, 返回值类型必须小于等于父类
  4. 建议: 重写的方法尽量和父类保持一致
  5. 只有被添加到虚方法表中的方法才能被重写
  • 私有方法 private 不能被重写
  • 静态放啊 static 不能被重写
03 继承中构造方法访问特点
  • 构造方法不能被子类继承
  • 子类中所有构造方法默认先访问父类中的无参构造(初始化父类数据), 再执行自己
  • 子类构造方法的第一行语句默认 super();, 不写也存在, 且必须在第一行

03 多态

java 时间减去8小时_java 时间减去8小时_20


创建的实例对象可以有多种形态, 使我们的代码更具灵活性 适用性

多态应用场景: 使用父类形参接收不同子类实参

多态: 同类型的对象, 表现出不同的形态

  • 表现形式: 父类类型 对象名称 = 子类对象;
  • 前提:
  1. 有继承关系
  2. 父类引用指向子类对象 Fu f = new Zi();
  3. 有方法重写 – 不同子类具有不同的行为
01 多态调用成员的特点
  • 变量调用: 编译看左边, 运行也看左边
  • 编译看左边: javac 编译代码的时候, 会看左边的父类中有没有这个变量, 如果有, 编译成功, 如果没有, 编译失败
  • 运行看左边: java 运行代码的时候, 实际获取的就是左边父类中成员变量的值,
  • 即使用多态创建对象, 访问变量时, 编译和运行都只在父类中查找,
  • 方法调用: 编译看左边, 运行看右边
  • 编译看左边: javac 编译代码时, 会看左边的父类中有没有这个方法, 如果有, 编译成功, 如果没有, 编译失败
  • 运行看右边: java 运行代码时, 实际上运行的是子类中的方法
  • 理解 Animal a = new Dog();
  • 现在用变量 a 调用变量和方法, 而 a 是父类类型的, 所以会从父类中寻找变量和方法
  • 所以, 对于成员变量调用, 若父类中没有, 子类中有, 则编译失败, 若父类子类中都有, 则使用父类中的成员变量, 即成员变量的调用看父类
  • 所以, 对于成员方法调用, 如果子类对方法进行了重写, 那么虚方法表中是会把父类的方法进行覆盖的(子类的方法不应该是在子类的虚方法表中吗, 如果在父类虚方法表中查找调用方法, 不应该还是父类的方法吗? 路过的看官大佬, 若对多态调用有更加详细的理解, 请在评论区留言, 感之不尽!!!)

java 中, 先加载父类字节码文件, 再加载子类字节码文件 (Object类字节码文件先加载)
所以, Animal a = new Dog(); 执行内存图如下

  • 当执行改行代码时, 先加载父类Animal字节码文件, 再加载子类Dog字节码文件, 子类继承父类虚方法, 且覆盖重写show()方法
  • 然后, 等式左边在栈内存的main方法内存中开辟一篇空间存储变量a
  • 等式右边在堆内存中开辟一片空间存储对象Dog, 且该空间中一部分存储父类变量, 一部分存储子类变量
  • 最后将堆内存中内存地址 001 赋值给栈内存中变量 a 空间中

    执行代码 sout(a.name); 调用变量
  • 编译看左边: 编译时, 查看堆内存中对象空间中存储父类变量的那部分空间中有没有变量 name
  • 运行看左边: 运行时, 查找堆内存中对象空间存储父类变量的那部分空间中变量 name 的值
  • 结果: 动物 执行代码 a.show();
  • 编译看左边: 编译时, 在父类方法中查找有没有对应方法
  • 运行看右边: 运行时, 去子类方法找

多态调用方法, 编译时 – 看父类

java 时间减去8小时_开发语言_21


多态调用方法, 运行时 – 看子类

java 时间减去8小时_父类_22


多态的优势:

  1. 在多态形式下, 右边对象可以实现解耦合, 便于扩展和维护
  2. 方法形参使用父类对象, 接受所有子类, 体现多态的扩展性和便利性

多态的劣势:

  1. 不能调用子类的特有方法. 因为, 父类中没有子类特有方法, 编译不通过
    + 解决方案: 向下转型
public static void main(String[] args) {
    Fu fu = new Zi();
    
    if(fu instanceof Zi){
        Zi zi = (Zi)fu;
    }
    
    // jdk14新特性 若fu为Zi类, 则将其转换为子类zi, 并返回true
      // 若fu不为Zi类, 则不转换, 并返回false
    if(fu instanceof Zi zi){
        //pass
    }
  }
}
小结

java 时间减去8小时_jvm_23

面向对象进阶

java 时间减去8小时_jvm_24

01 static – 共享

  • static 表示静态, 是 java 中的一个修饰符, 可以修饰成员方法和成员变量, 称之为静态变量和静态方法
  • 静态变量与静态方法属于类, 为所有实例化对象共享
  • static 修饰的对象特点:
  1. 不属于对象, 属于类
  2. 被该类所有对象共享
  3. 随着类的加载而加载, 即优先于对象的加载, 即优先于对象的创建和存在
  4. 静态方法多用在测试类和工具类中
  5. javabean 类中很少使用
  • 调用方式
  1. 类名调用
  2. 对象名调用
  • static–note
  1. 静态方法只能访问静态变量和静态方法
  2. 非静态方法可以静态变量和静态方法, 也可以访问非静态的成员变量和非静态成员方法
  3. 静态方法中没有 this 关键字

01 static 静态对象(成员变量与成员方法)内存图

  • 静态变量随着类的加载(类的字节码加载进内存)而加载, 优先于对象出现
  • 静态变量的存储空间在堆内存中单独开辟一片空间

    将 “啊玮老师” 赋值给堆内存中静态存储区的变量 “teachername”

    类的实例化对象指向类的静态区

    静态区的资源所有对象共享

02 小结

java 时间减去8小时_父类_25

02 认识main方法

java 时间减去8小时_开发语言_26


main方法中args数组传值处

01

java 时间减去8小时_java_27


02

java 时间减去8小时_父类_28


03

public static void main(String[] args) {
        System.out.println(args.length);
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]); // 输出 111
        }
    }

03 包

包: 管理与不同的java类
包名规则: 公司域名反写 + 包的作用, 全部小写
全类名 (全限定名) = 包名+类名

可以这样写哦

java 时间减去8小时_jvm_29


还是这样写吧

java 时间减去8小时_父类_30


使用其他类的规则:

  1. 使用同一个包中的类, 不需要导包
  2. 使用java.lang包中的类, 不需要导包
  3. 其他情况都需要导包
  4. 如果使用两个包中的同名类, 需要使用全类名

04 final 关键字

java 时间减去8小时_父类_31


方法: 当该方法表示一种规则, 不希望被改变时, 使用 final 修饰

类: final class 类名{} 如 String 类 public final class String ... String里面的方法你都不要动哦, final 修饰的类也不可被继承

变量: 一次赋值后不可改变, 赋值后变为常量

final int a;
a = 10;

常量

  1. 命名规则
  • 全部大写, 单词之间用下划线隔开
  1. note
  1. final 修饰的变量是基本数据类型, 那么变量存储的数据值不能改变
  2. final 修饰的变量是引用数据类型, 那么变量存储的地址值不能改变, 但地址指向的对象内部数据值可以改变 比如对象名.setName(“111”);, 修改对象名的name属性吗但对象名存储的地址不可改变

note

  1. 字符串不可变, 就是有使用 final 修饰

05 权限修饰符

  • 权限修饰符: 用来控制一个成员能够被访问的范围
  • 成员: 变量, 方法, 构造方法, 类

权限修饰符作用范围

java 时间减去8小时_java 时间减去8小时_32


note: 实际开发中, 一般只用 public private

  1. 成员变量私有
  2. 方法一般使用public, 若方法中的代码是其他方法的共性代码, 这个方法一般也定义为私有

06 代码块

  • 局部代码块
  • 构造代码块
  • 静态代码块

01 局部代码块 – 淘汰

  • 写在方法里面的, 用大括号包住, 生命周期是一个大括号
  • 作用: 提前结束变量的生命周期

02 构造代码块 – 淘汰

理解:

  1. 写在成员位置的代码块
  2. 作用: 可以把多个构造方法中重复的代码抽取出来
  3. 执行时机: 在创建本类对象时, 优先于构造方法执行
示例代码:
public class Student {
    //构造代码块:
    //1.写在成员位置的代码块
    //2.作用:可以把多个构造方法中重复的代码抽取出来
    //3.执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法
    //渐渐的淘汰了
    {
        System.out.println("开始创建对象了");
    } // 这就是构造代码块

    public Student() {
        System.out.println("空参构造");
    }

    public Student(String name, int age) {
        System.out.println("有参构造");
        this.name = name;
        this.age = age;    
}

03 静态代码块

格式: static{代码块} 特点: 随着类的加载而加载, 自动触发, 且执行一次, 即当第一次使用该类时执行, 即使第二次创建该类对象, 也不会执行
使用场景: 在类加载的时候, 做一些数据初始化的时候使用

07 abstract

抽象方法所在的类就是抽象类, 不能确定具体的方法体的将方法定义为抽象方法, 没有方法体, 所属类称为抽象类, 子类必须重写父类中的抽象方法

定义格式:

  • public abstract 返回值类型 方法名(参数列表); 重写时, 去掉abstract
  • public abstract class 类名{} 特点:
  1. 抽象类不能实例化
  2. 抽象类中不一定有抽象方法, 有抽象方法的类一定是抽象类
  3. 抽象类可以有构造方法 – 创建子类对象时, 为父类中的公共数据初始化
  4. 抽象类的子类
  1. 必须重写父类所有抽象方法
  2. 或者子类也定义为抽象类

08 interface

  • 接口: 一系列规则, 规范的方法的接口
  • 抽象: 一类事物共性的抽取

java 时间减去8小时_java_33


java 时间减去8小时_开发语言_34

01 接口的定义和使用

  • 接口使用关键字 interface 定义
    public interface 接口名{}
  • 接口也不能实例化, 因为它里面的方法也有 抽象方法, 供子类实现
  • 接口与类是实现的关系
    public class 类名 implements 接口名{}
  • 接口的子类(实现类)
  1. 要么重写接口中所有抽象方法
  2. 要么是抽象类
  • 接口之间不能 implements, 可以 extends
  • 接口也具有多态的特性, 与类的多态一样

note:

  1. 类实现接口, 可以是多实现
    public class 类名 implements 接口名1, 接口名2{}
  2. 实现类可以在继承一个类的同时实现接口
    public class 类名 extends 父类 implements 接口名1, 接口名2{}

02 接口中成员的特点

  • 成员变量
  • 只能是常量
  • 默认修饰符: public static final
  1. final: 一次赋值, 不可修改
  2. static: 方便调用 – 接口名.变量名
  3. public: 可以在任意处访问
  • 构造方法
  • 没有 – 不需要给实现类赋值
  • 成员方法
  • 只能是抽象方法 – jdk7以前
  • 默认修饰符 public abstract

03 接口和类之间的关系

  • 类和类 – 单继承, 可多层继承
  • 类和接口 – 单实现 / 多实现(重写所有接口的抽象方法) / 边继承 边实现
  • 若实现多个接口时, 出现重名方法怎么办??? : 重写一次就可, 表示将多个接口的重名方法都实现了
  • 接口和接口 – 继承关系, 可以单继承也可多继承, 需要注意的是: 实现类需要实现所有相关接口的抽象方法

04 接口扩展

01 jdk8开始接口中新增的方法
  • jdk8: 接口中可以定义有方法体的方法(默认 静态)
  • jdk9: 接口中可以定义私有方法

jdk7的接口, 问题来了, 当接口新添加一个抽象方法时, 它的实现类就得立即重写该抽象方法, 造成不便

java 时间减去8小时_java 时间减去8小时_35


怎么办? – 在接口中可以添加有方法体的方法

  • 允许在接口中定义默认方法, 使用关键字 default 修饰
  • 接口中默认方法定义格式 public default 返回值类型 方法名(参数列表){}
  • 默认方法不强制重写, 重写时, 去掉 default 关键字
  • public 可以省略, default 不能省略
  • 如果实现了多个接口, 多个接口中存在同名的默认方法, 子类就必须对该方法进行重写
  • 允许在接口中定义静态方法, 使用关键字 static 修饰
  • 接口中静态方法定义格式: public static 返回值类型 方法名(参数列表){}
  • 静态方法只能通过接口名调用, 不能通过实现类名或者对象名调用
  • public 可以省略 static 不可省略
  • 静态方法不能重写 (重写: 子类覆盖继承自父类虚方法表中的方法, 使用关键字 static 修饰的方法不在虚方法表中)

又有问题了 当接口中出现重复代码时, 这些代码只在接口内部使用, 不希望外部使用, 因此 jdk9 新增了私有方法
接口中私有方法的定义格式:

  • private 返回值类型 方法名(参数列表){} – 供 default 方法使用
  • private static 返回值类型 方法名(参数列表){} – 供 static 方法使用
02 接口应用
03 3适配器设计模式
  • 适配器设计模式: 解决接口与接口实现类之间的矛盾问题
  • InterAdapter: 创建一个 InterAdapter 对接口做一个空实现, 这样就可以创建只实现接口中特定方法的实现类, 同时 InterAdapter 不需要创建实例化对象, 所以将 InterAdapter 定义为 abstract 抽象类

09 内部类

类的五大成员: 属性 方法 构造方法 代码块 内部类
内部类: 内部类表示的事物是外部类的一部分, 内部类单独出现没有意义.

  • 在一个类的里面, 再定义一个类
public class Outer{ // 外部类
	public class Inner{ // 内部类
	}
}

public class Test{ // 外部其他类
	public static void main(String[] args){
	
	}
}
  • 内部类的访问特点
  • 内部类可以直接访问外部类的成员, 包括私有
  • 外部类要访问内部类的成员, 必须创建对象

01 内部类分类

  • 成员内部类 – 写在成员位置的, 属于外部类的成员
  1. 代码书写
  • 写在成员位置
  • 成员内部类可以被一些修饰符所修饰 private 默认 protected public static
  • jdk16之后, 内部类才可以定义静态变量
  1. 内部类创建格式
  1. 方式一 在外部类中编写方法, 对外提供内部类的对象
public class Outer{
	private class Inner{
	}
	
	public Inner getInstance(){
		return new Inner();
	}
}
// 其他类调用外部类方法创建内部类对象
public class Test {
	public static void main(String[] args) {
	Object o = new Outer().getInstance();
	System.out.println(o);  // demo.Outer$Inner@1b6d3586  $:表示内部类
	}
}
  1. 方式二 直接创建 外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();
  1. 成员内部类获取外部类对象属性和方法
public class Outer {
	private int a = 10;
	private int b = 10;

	class Inner{
        private int a = 20;

		public void show(){
    		int a = 30;
   			System.out.println(b); // 10
   	 		System.out.println(a); // 30
    		System.out.println(this.a); // 20
    		System.out.println(Outer.this.a); // 1o
		}
	}
	public Inner getInstance(){
		return new Inner();
	}
}

内存图分析 – 内部类访问局部变量、本类成员变量、外部类成员变量
说明:

  • 类中的方法都有一个隐藏参数 本类名 this, 即 this 指代当前调用该方法的对象
  • 内部类中有一个隐藏成员变量 Outer this; 此处this指向外部类, 用于内部类访问外部类
  • 静态内部类
    使用 static 修饰的成员内部类就是静态内部类
    静态内部类只能访问外部类中的静态变量和静态方法, 如果想要访问非静态的需要创建对象
    创建格式:外部类名.内部类名 对象名 = new 外部类名.内部类名()外部类名.内部类名.静态方法名()调用静态内部类方法:
  1. 调用内部类非静态方法: 先创建内部类对象 再调用
  2. 调用内部类静态方法:使用类名调用也可以 外部类名.内部类名.方法名();
  • 局部内部类
  1. 将内部类定义在方法里面就叫局部内部类, 类似于方法里面的局部变量
  2. 外界无法直接使用, 需要在方法内部创建局部内部类对象并使用
  3. 该类可以直接访问外部类的成员,也可以访问方法内部的局部变量
  • 匿名内部类
    匿名内部类本质上就是隐藏了名字的内部类,可以写在成员位置或局部位置 – 继承父类或实现子类
    格式
new 类名或接口名(){
	重写方法
}; // 不要忘了匿名内部类的大括号后面接分号

// 格式说明
1. 继承和实现:继承和实现类名或接口名表示的抽象类或接口
2. 方法重写:对继承和实现的对象需要重写的方法进行重写
3. 创建对象:new 关键字表示创建对象
# 整体理解: 大括号表示的是子类或是实现类(匿名内部类),类名或接口名表示的是继承的父类或实现的子类,new 关键字表示的是创建大括号表示的类的对象(匿名内部类对象)。整体就是一个类的子类对象或接口的实现类对象

**应用场景:**如调用方法的实参传入一个匿名内部类, 或赋值给父类或接口

tip:在命令行窗口使用 javap 反编译java.class文件,查看字节码文件表示的内容

10 浅克隆和深克隆

  • 浅克隆: 不管对象内部的属性是基本数据类型还是引用数据类型, 都完全拷贝过来, 即 拷贝的是变量中存储的值, 基本数据类型拷贝数据值, 引用数据类型拷贝地址值
  • 深克隆: 基本数据类型不变, 字符串复用(常量池中的字符串的地址复用), 引用数据类型重新开辟一片空间使用

11 转义字符

转义字符的说明

/* 转义字符
         * \ 是转义字符 改变其后面那个字符的原本含义
         * 比如: " -- 双引号, 在 java 中有特殊的含义: 表示一个字符串的开始或结尾
         *       当需要打印一个双引号时, 需要用到转义字符, 将其含义由独特表示转换为一个普通的双引号
         *       System.out.println(" \" ");
         * 又比如: java 中路径的表示 \\ 使用双斜杠
         *        表示: 前一个斜杠是转义字符, 将后一个斜杠转义字符转义为普通斜杠
         *        如果, 只写一个斜杠, 表示的是 该转义字符 \ 将其后面的字符进行了转义
         */

11 正则表达式 Regex

note: 帮助文档 查 pattern

正则表达式是一个字符串
可以校验字符串是否满足一定的规则, 并用来校验数据格式的合法性

作用:

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

01 校验字符串

java 时间减去8小时_开发语言_36


代码示例

// 只匹配一个 -- 即只对单个字符进行判断
        System.out.println("a".matches("[abc]")); // true
        System.out.println("b".matches("[abc]")); // true
        System.out.println("c".matches("[abc]")); // true
        // 判断两个字符的字符串, 可以写两个正则规则
        System.out.println("ab".matches("[abc]")); // false
        System.out.println("ab".matches("[abc][abc]")); // true

        /* 转义字符
         * \ 是转义字符 改变其后面那个字符的原本含义
         * 比如: " -- 双引号, 在 java 中有特殊的含义: 表示一个字符串的开始或结尾
         *       当需要打印一个双引号时, 需要用到转义字符, 将其含义由独特表示转换为一个普通的双引号
         *       System.out.println(" \" ");
         * 又比如: java 中路径的表示 \\ 使用双斜杠
         *        表示: 前一个斜杠是转义字符, 将后一个斜杠转义字符转义为普通斜杠
         *        如果, 只写一个斜杠, 表示的是 该转义字符 \ 将其后面的字符进行了转义
         */
        System.out.println("---------------------------------");
        
        // 使用预定义字符判断单个字符
        System.out.println("我".matches(".")); // true . 匹配任意一个字符
        System.out.println("我是".matches("..")); // true 多个字符, 每一个字符都需要一个判断
        System.out.println("我是".matches(".")); // false
        System.out.println("我是".matches("...")); // false

        System.out.println("---------------------------------");

        // 判断数字
        System.out.println("0".matches("\\d")); // true
        System.out.println("12".matches("\\d\\d")); // true
        System.out.println("123".matches("\\d\\d")); // false
        System.out.println("12".matches("\\d")); // false

匹配多个字符

java 时间减去8小时_开发语言_37


代码示例

// 一次匹配多个字符
        // 必须是字符 下划线 字母 至少6为
        System.out.println("123456a_".matches("\\w{6,}")); // true
        System.out.println("12a_".matches("\\w{6,}")); // false

        // 必须是数字 字母 且必须只能是4位
        System.out.println("1234".matches("[0-9a-zA-Z]{4}")); //true
        System.out.println("1a2Aq".matches("[0-9A-Za-z]{4}")); // false
        System.out.println("23df".matches("[\\w&&[^_]]{4}")); // true
        System.out.println("23d_".matches("[\\w&&[^_]]{4}")); // false

02 爬虫

介绍两个类:

  • Pattern: 表示正则表达式
  • Matcher: 文本匹配器 – 即按照正则表达式的规则去读取字符串, 从头开始读取, 在大串中寻找符合匹配规则的字串

代码示例

public static void main(String[] args) {
        //new MainJFrame();

        String text = "java是世界上最好的语言, java8真好用, java11真不错!!!";

        // 使用 Pattern 和 Matcher 对 text 查询 javaXX 字段

        Pattern pattern = Pattern.compile("java\\d{0,2}");
        Matcher m = pattern.matcher(text);

        // 调用 Matcher 对象的 find 方法, 判断 text 中是否有满足 pattern 的字段
        // find: 返回 boolean, 并且保留查询到的字段的开始索引和结束索引+1 -- (start, end+1)
        //m.find();

        // 调用 Matcher 对象的 group 方法
        // group: 底层根据 find 记录的 (start, end+1) 截取 text, 即将查询到的字段以字符串的形式返回
        // 同理subString(start,end+1); 返回索引 (start, end) 的字段
        //String s = m.group();

        // 再次调用 find, 从当前位置继续向后查找, 查询第二个符合条件的字段, 所以使用循环
        boolean flag = true;
        while (flag){
            flag = m.find();

            if (!flag){
                break;
            }

            String str = m.group();

            System.out.println(str);
        }
    }

03 正则表达式在字符串方法中的使用

这里直接使用字符串的对应方法, 即可按照参数中正则表达式的规则, 操作字符串

java 时间减去8小时_java_38


说明

  1. str1.matches(regex1); – 判断 str1 是否符合 regex1
  2. str1.replaceAll(regex1, str2); – 将 str1 中符合 regex1 的部分替换位 str2
  3. str1.split(regex1); – 按 str1 中符合 regex1 的部分, 将 str1 进行切割

注意事项

  1. 正则表达式一个匹配范围对应一个字符, 多个字符即字符串的匹配需要使用多个匹配范围
  2. 当同时匹配不同字符串时, 可以使用 | 符号. 如: (正则表达式1) | (正则表达式2)
  3. 贪婪爬取 "a+" – 多少个a都要
  4. 非贪婪爬取 "a+?" – 一长串a时, 只要第一个就好
  5. 贪婪爬取和非贪婪爬取主要适用于 + *
01 非捕获分组–代码示例
public static void demo(){
        String text = "Java8 java11 jAva11 java是世界上最好的语言, java,有很多版本, 比如java9, java10, java8真好用, java11真不错!!!";

        // 正则表达式联系

        // 1. 查询 带有版本号的java, 但是只要8和11
        String regex1 = "(?i)java(?=8|11)";
        String regex2 = "(?i)java(?:8|11)";
        String regex3 = "(?i)java(8|11)"; // 和 regex2 功能一样
        String regex4 = "(?i)java(?!8|11)"; //
        /*
        ?表示占位符, 表示java
        =表示将java与后面的字符拼接
        即 regex1 表示 java8 | java11
        但是:使用Matcher对象的group方法获取字符串时, 只获取?表示的数据 java
        (?i) 忽略大小写
        : 获取时带上后面的数据 8 | 11
        ! 匹配除了java8 java11的其他javaXX, 并只获取?表示的数据
         */

        Pattern p =Pattern.compile(regex4);

        Matcher m = p.matcher(text);

        while(m.find()){
            System.out.println(m.group());
        }
    }

上面代码主要说的就是非捕获分组

java 时间减去8小时_java_39


代码示例

java 时间减去8小时_java_40

02 分组 ()

分组

java 时间减去8小时_父类_41


捕获分组

java 时间减去8小时_jvm_42

public static void demo2(){
        // 捕获分组
        String regex1 = "(.)(.+)\\1";
        // \\组号 : 表示把第 X 组的内容拿出来, 再用一次, 即当前组的匹配规则和 X 组的匹配规则一样
    }

java 时间减去8小时_java_43


代码示例

java 时间减去8小时_开发语言_44


总结

java 时间减去8小时_jvm_45

API

application programming interface
应用程序编程接口

API帮助文档

如何使用帮助文档

java 时间减去8小时_开发语言_46

01 字符串

java 时间减去8小时_jvm_47

01 String

string概述
java.lang.String 类代表字符串, java程序中所有字符串文字(如:“abc”)都为此类对象

字符串的内容不会发生改变, 它的对象创建后值不可改变

String name = "zhangsan";
name = "lisi"

需要强调的是, 上述代码中, 并没有发生字符串的改变, 只是创建了两个不同的字符串, 改变了name的指向

创建String方式

  1. 根据字符数组或字节数组创建字符串, 字节数组转成对应的ascii值转换成字符串

java内存之字符串常量池

  • 只有使用直接赋值的方式创建的字符串才在字符串常量池中, jdk7之后, 字符串常量池位于堆内存中
  • 当使用双引号直接赋值时, 系统会检查该字符串在常量池中是否存在,
  • 存在: 复用–将其地址赋值给对应字符串变量
  • 不存在: 创建新的

    通过构造方法创建字符串, 不能复用, 浪费内存空间
01 Stirng 方法

01 比较

  • “==” 比较的是什么 – 变量空间中存储的是数据
  • 基本数据类型比较的是自己空间中的数据值
  • 引用数据类型比较的是自己空间中的地址值

    比较两个字符串的值
    直接使用双等号比较符比较的是地址值, 所以一般使用string方法equals比较两个字符串表示的值是否一样
public static void main(String[] args) {
        String a = "abc";
        String b = "abc";
        String c = new String("abc");
        System.out.println(a==b); // true
        System.out.println(a==c); // false 此处比较的是地址值
        System.out.println(a.equals(c)); // true 调用方法比较的是字符串值
    }

根据索引返回字符

java 时间减去8小时_开发语言_48

02 StringBuilder

String Builder: StringBuilder是一个内容可变的容器, 效率高于String

  • 作用: 提高字符串的操作效率
01 构造方法

java 时间减去8小时_父类_49

02 常用方法

java 时间减去8小时_开发语言_50


note: 在用 StringBuilder 操作完之后, 需要调用其 sb.toString() 方法, 将Stringbuilder对象变量重新转换为String对象

03 StringJoiner

  • StringJoiner 和 StringBuilder 一样, 也可以看成一个容器, 创建后里面的内容也是可变的
  • 作用: 提高字符串操作效率, 而且代码编写简洁
  • jdk8
01 构造方法

指定间隔符号以及开始和结束符号

java 时间减去8小时_jvm_51

02 成员方法

java 时间减去8小时_父类_52


java 时间减去8小时_java_53

04 字符串底层原理

字符串存储的内存原理

  • 直接赋值会复用字符串常量池中的 – 字符串常量池位于堆中
  • new 出来的不会复用 – 单独在堆中开辟一片空间, 用于存放 new 出来的字符串对象

== 号的比较

  • 基本数据类型比较的是变量表示空间中的数据值
  • 引用数据类型比较的是变量表示空间中的地址值

字符串拼接底层原理

  • 如果没有变量参与, 都是字符串直接相加, 会在编译javac之后, 将其直接转换为多个字符串想加的最终结果, 会复用字符串池中的字符串, 提高效率
  • 如果有变量参与, 会创建新的字符串, 浪费内存

StringBuilder

  • 原理: 所有要拼接的内容都会往 StringBuilder 中放, 不会创建很多无用的中间字符串, 节约内存

02 ArrayList–集合

定义: 可以自动扩容即**长度可变(底层自动实现)**的数组
note:

  • 存储类型: 集合只能存储引用类型, 基本类型需要使用包装类

java 时间减去8小时_开发语言_54


基本数据类型对应的包装类 – jdk1.5之后自动转换

java 时间减去8小时_开发语言_55

01 ArrayList

java 时间减去8小时_开发语言_56

  • <E>: 表示泛型, 用于限制ArrayList存储的数据类型
  • 输出打印arraylist对象名, 为 [元素1, 元素2]

01 创建 – 空参构造

public static void main(String[] args) {
        ArrayList arr1 = new ArrayList(); // 无泛型限制的集合, 可以add任意类型的数据
        arr1.add(1);
        arr1.add("abc");
        System.out.println(arr1.get(0));
        System.out.println(arr1.get(1));
        System.out.println(arr1); // [1, abc] 输出打印结果

        ArrayList<Integer> arr2 = new ArrayList<>(); // 有泛型限制的集合, 只能添加泛型限制的数据类型的数据
        arr2.add(1);
        // arr2.add("abc"); error!!! 只能添加 Integer 类型的数据
    }

02 成员方法

java 时间减去8小时_父类_57

03 System

提供一些与系统相关的方法

java 时间减去8小时_开发语言_58

04 Runtime

java 时间减去8小时_java 时间减去8小时_59


Runtime 由java给出, 在如下代码中表明, 程序中创建的 Runtime 对象 只能是同一个

java 时间减去8小时_java_60


运行cmd命令

如: shutdown -s 默认一分钟后关机

shutdown -s -t 指定多少秒后关机

shutdown -a 取消关机操作

shutdown -r 关机并重启

05 Object

  • Object 是Java的顶级父类
  • 没有成员变量 – 没有一个属性是所有类共有的, 所以只有空参构造, 所以类的构造方法默认调用的是父类的空参构造

java 时间减去8小时_父类_61


object的clone方法是浅克隆

equals() 在object中是比较地址值, 即直接比较两个变量

java 时间减去8小时_java 时间减去8小时_62

06 Objects

Objects 是一个工具类, 提供了一些操作对象方法供我们使用

java 时间减去8小时_java_63

07 BigInteger

BigInteger: 就是获得一个大的整数

01 构造方法

java 时间减去8小时_java_64


note:

  • 使用静态方法获取 BigInteger 对象, 内部有优化
  1. 表示的范围较小, 只能表示 long 的取值范围之内
  2. 在内部对常用的数字进行了优化( -16 ~ 16)
  • 提前把 -16 ~ 16 的 BigInteger 对象先创建好, 如果多次获取不会重新创建新的对象
  • 对象一旦创建, 内部记录的值就不能发生改变
  • 即, 只要进行计算都会产生一个新的 BigInteger 对象

02 成员方法

java 时间减去8小时_java 时间减去8小时_65


BigInteger 是对象, 不能直接进行四则运算BigInteger 底层存储数据原理

java 时间减去8小时_java_66


java 时间减去8小时_父类_67


java 时间减去8小时_java 时间减去8小时_68


目前内存扛不住的

java 时间减去8小时_java_69

08 BigDecimal

作用: 解决小数计算不精确的问题

  • 用于小数的精确计算
  • 用来表示很大的小数

小数计算问题如下

System.out.println(0.01); // 0.01
        System.out.println(0.09); // 0.09 
        System.out.println(0.01 + 0.09); // 0.09999999999999999

        double d1 = 0.01;
        double d2 = 0.09;
        System.out.println(d1); // 0.01
        System.out.println(d2 ); // 0.09 
        System.out.println(d1 + d2 ); // 0.09999999999999999

        BigDecimal bd1 = new BigDecimal(0.01); 
        BigDecimal bd2 = new BigDecimal(0.09);
        System.out.println(bd1); // 0.01000000000000000020816681711721685132943093776702880859375
        System.out.println(bd2); // 0.0899999999999999966693309261245303787291049957275390625

        BigDecimal bd3 = new BigDecimal("0.01");
        BigDecimal bd4 = new BigDecimal("0.09");
        System.out.println(bd3); // 0.01
        System.out.println(bd4); // 0.09
        System.out.println(bd3.add(bd4)); // 0.10

构造方法

  • public BigDecimal(double val) – 该方法有不可预知的不确定性 不建议使用
  • public BigDecimal(String val) – 该方法没有第一个构造放啊的不确定性
  • public static BigDecimal valueOf(double val) – 通过静态方法获取 BigDecimal 对象

note:

  1. 如果表示的数字不大, 没超过double的取值范围, 建议使用静态方法
  2. 如果表示的数字过大, 建议使用第二个构造方法
  3. 使用静态方法时, 如果传递的是 0-10之间的整数, 多次调用, 返回的是具有相同地址值的同一个对象

成员方法

java 时间减去8小时_java 时间减去8小时_70

09 Date

01 jdk7前时间相关类

  1. Date – 时间
  2. SimpleDateFormat – 格式化时间
  3. Calendar – 日历

代码示例

Date

java 时间减去8小时_jvm_71


java 时间减去8小时_父类_72


SimpleDateFormat

作用:

  1. 格式化: 把时间变成我们喜欢的格式
  2. 解析: 把字符串表示的时间变成 date 对象

格式化: 调用 SimpleDateFormatformat 方法, 将一个 Date 对象转换称我们需要的时间格式, 返回一个字符串
解析: 调用 SimpleDateFormatparse 方法, 将一个表示时间的字符串转换成 Date 对象, 以供后续操作

java 时间减去8小时_jvm_73


代码示例

java 时间减去8小时_父类_74


java 时间减去8小时_父类_75


Calendar

java 时间减去8小时_java_76


java 时间减去8小时_java 时间减去8小时_77


note

  1. 获取日历对象
  • Calendar.getInstance(); – 底层原理: 根据系统的不同时区来获取不同的日历对象, 会把时间中的纪元 年 月 日 时 分 秒 星期 等都放到一个数组中, 默认表示当前时间
  • 在日历对象中, 月 0-11 星期日是一个星期的第一天
  • add 正数对某个字段加 负数对某个字段减

02 jdk8新增时间相关类

java 时间减去8小时_开发语言_78


java 时间减去8小时_java 时间减去8小时_79


java 时间减去8小时_父类_80

01 ZoneID

java 时间减去8小时_java 时间减去8小时_81

java 时间减去8小时_父类_82

02 Instant 时间戳

获取一个不带时区的时间, 即标准时区的时间

java 时间减去8小时_开发语言_83


代码示例

java 时间减去8小时_父类_84


java 时间减去8小时_开发语言_85

03 ZoneDateTime

java 时间减去8小时_开发语言_86


代码示例

java 时间减去8小时_jvm_87


java 时间减去8小时_java_88


java 时间减去8小时_jvm_89

04 DateTimeFormatter

DateTimeFormatter 用于时间的格式化和解析

java 时间减去8小时_java_90

05 LocalDate LocalTime LocalDateTime
  • Localdate : 年 月 日
  • LocalTime: 时 分 秒
  • LocalDateTime: 年 月 日 时 分 秒

    转换

    代码示例



    LocalTime

java 时间减去8小时_开发语言_91


java 时间减去8小时_java 时间减去8小时_92


LocalDateTime

java 时间减去8小时_java_93


java 时间减去8小时_jvm_94

06 Duration Period ChronoUnit

java 时间减去8小时_java 时间减去8小时_95


java 时间减去8小时_jvm_96

10 包装类

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

java 时间减去8小时_开发语言_97


java 时间减去8小时_jvm_98


java 时间减去8小时_jvm_99

以 Integer 为例

这是jdk5以前, 现在直接用就好

java 时间减去8小时_父类_100


note

  1. radix 表示进制
  2. 静态方法对-127 ~ 128 (128- -127 + 1 =256) 256个Integer对象建立了一个数组, 获取对象时, 直接从数组中获取
  3. jdk5之后, 可以自动拆箱和装箱

Integer 成员方法

java 时间减去8小时_父类_101


note:

  1. 使用 Integer 类型转换方法 parseInt() 时, 字符串必须是数字
    2 除了 Character 类型, 其他类型都有 parseXxx() 方法

补充

  1. 键盘录入 使用 nextLine() 返回一个字符串
private static void testKeyboard() {
    // 键盘录入
    Scanner sc = new Scanner(System.in);

    System.out.println("请输入: ");

   	//System.out.println(sc.next());
   	/*
    使用获取特定类型的方法的局限性:
        1. 遇到空格 制表符等停止, 无法接收后面的内容
        2. 建议使用 nextLine(), 遇到回车停止
     */
    
    System.out.println(sc.nextLine());
 }

10 Arrays

java 时间减去8小时_jvm_102

插件

  1. ptg:一键生成标准javabean
  2. Translation: 翻译插件, 如将源码中的英文注释翻译成中文

案例 – 拼图小游戏

java 时间减去8小时_父类_103


java 时间减去8小时_java 时间减去8小时_104


java 时间减去8小时_java 时间减去8小时_105

java 时间减去8小时_jvm_106


java 时间减去8小时_开发语言_107

java 时间减去8小时_java_108

java 时间减去8小时_java_109


java 时间减去8小时_java 时间减去8小时_110

java 时间减去8小时_父类_111

java 时间减去8小时_java_112


java 时间减去8小时_父类_113


java 时间减去8小时_开发语言_114


事件:

  • 事件就是可以被组件识别的操作
  • 当你对组件干了某件事情之后,就会执行对应的代码
  • 三属性
  • 事件源 – 按钮 图片
  • 事件 – 某些操作,鼠标点击等
  • 绑定监听


    美化界面



    查看完整图片 A 键
    一键通关 W 键
  1. 整个游戏界面添加键盘事件监听
  2. 编写相应的逻辑代码

判断胜利 使用win二维数组
3. 胜利后显示胜利图片
4. 胜利后取消键盘监听事件

计数功能

  • 使用 JLabel 类(管理图片和文字)

java 时间减去8小时_jvm_115