java小白第二天

4 篇文章 0 订阅
2 篇文章 0 订阅

java小白第二天

00 写在前面

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

01 面向对象

内容目录架构
在这里插入图片描述

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 long0
    float double0.0
    char" " 空格
    booleanfalse
    String等引用类型null
类的相关总结

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

修饰符名称作用备注
privateprivate修饰的成员只能在类中被直接访问类中成员变量都用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内存分配介绍
在这里插入图片描述
字节码文件原来在方法区中, 现在在元空间中, 当运行一个类时, 就会加载其字节码文件到内存

方法区, 栈内存, 堆内存存储内容如下:
方法区: 加载字节码文件进入内存
栈: 方法运行时进入的内存, 方法中创建的变量也在这里
堆: 凡是 new 出来的东西都在堆内存中, 并开辟相应空间产生地址标记
在这里插入图片描述

01 一个对象的内存图

Student s = new Student();

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

  1. 加载class文件–加载Student类的字节码文件
  2. 声明局部变量–s
  3. 在堆内存中开辟一个空间–new Student()
  4. 默认初始化
  5. 显示初始化
  6. 构造方法初始化
  7. 将堆内存中的地址值赋值给左边的局部变量
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    当栈中所有方法执行完毕, 弹出栈后, 堆内存对应的空间就没有变量指向, 此时, 堆内存对应的空间也即变为垃圾空间, 内存空间被收回
    在这里插入图片描述
    堆内存对应的空间也即变为垃圾空间, 内存空间被收回
    在这里插入图片描述
02 多个对象的内存图

类的字节码文件只加载一次进内存
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

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

this的内存图
在这里插入图片描述

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

图示如下
在这里插入图片描述

03 面向对象的三大法宝

封装 继承 多态

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

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

当类与类之间, 存在相同(共性)的内容, 并满足子类是父类中的一种, 就可以考虑使用继承, 来优化代码
在这里插入图片描述
01 继承格式:
public class Student extends Teacher{}

02 继承的特点

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

父类中的内容大概分为三类如下:
构造方法
成员变量
成员方法
在这里插入图片描述
进一步说明
在这里插入图片描述
01 构造方法不能被继承

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

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

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

在这里插入图片描述
03 方法继承 – 子类可以继承父类中虚方法

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

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

虚方法表 – 子类调用一个方法, 若是虚方法, 就去虚方法表中找, 提高效率. 此外, 若子类调用的方法不是虚方法, 子类会现在自己类中查找, 若没有, 则会一层一层向上查找
在这里插入图片描述
示例内存图
在这里插入图片描述

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

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

访问顺序:

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

示例图
在这里插入图片描述
在这里插入图片描述

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

同样遵循就近原则

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

01 方法的重写

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

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

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

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

02 书写格式

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

03 方法重写的注意事项

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

03 多态

在这里插入图片描述
创建的实例对象可以有多种形态, 使我们的代码更具灵活性 适用性

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

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

  • 表现形式: 父类类型 对象名称 = 子类对象;
  • 前提:
    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();
  • 编译看左边: 编译时, 在父类方法中查找有没有对应方法
  • 运行看右边: 运行时, 去子类方法找

多态调用方法, 编译时 – 看父类
在这里插入图片描述
多态调用方法, 运行时 – 看子类
在这里插入图片描述
多态的优势:

  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
    }
  }
}
小结

在这里插入图片描述

面向对象进阶

在这里插入图片描述

01 static – 共享

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

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

  • 静态变量随着类的加载(类的字节码加载进内存)而加载, 优先于对象出现
  • 静态变量的存储空间在堆内存中单独开辟一片空间
    在这里插入图片描述
    将 “啊玮老师” 赋值给堆内存中静态存储区的变量 “teachername”
    在这里插入图片描述
    类的实例化对象指向类的静态区
    在这里插入图片描述
    静态区的资源所有对象共享
    在这里插入图片描述

02 小结

在这里插入图片描述

02 认识main方法

在这里插入图片描述
main方法中args数组传值处
01
在这里插入图片描述
02
在这里插入图片描述
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类
包名规则: 公司域名反写 + 包的作用, 全部小写
全类名 (全限定名) = 包名+类名

可以这样写哦
在这里插入图片描述
还是这样写吧
在这里插入图片描述
使用其他类的规则:

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

04 final 关键字

在这里插入图片描述
方法: 当该方法表示一种规则, 不希望被改变时, 使用 final 修饰
类: final class 类名{} 如 String 类 public final class String ... String里面的方法你都不要动哦, final 修饰的类也不可被继承
变量: 一次赋值后不可改变, 赋值后变为常量

final int a;
a = 10;

常量

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

note

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

05 权限修饰符

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

权限修饰符作用范围

在这里插入图片描述
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

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

在这里插入图片描述
在这里插入图片描述

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的接口, 问题来了, 当接口新添加一个抽象方法时, 它的实现类就得立即重写该抽象方法, 造成不便
在这里插入图片描述
怎么办? – 在接口中可以添加有方法体的方法

  • 允许在接口中定义默认方法, 使用关键字 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之后, 内部类才可以定义静态变量
    2. 内部类创建格式
      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  $:表示内部类
        	}
        }
        
      2. 方式二 直接创建 外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();
    3. 成员内部类获取外部类对象属性和方法
      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 校验字符串

在这里插入图片描述
代码示例

// 只匹配一个 -- 即只对单个字符进行判断
        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

匹配多个字符
在这里插入图片描述
代码示例

// 一次匹配多个字符
        // 必须是字符 下划线 字母 至少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 正则表达式在字符串方法中的使用

这里直接使用字符串的对应方法, 即可按照参数中正则表达式的规则, 操作字符串
在这里插入图片描述
说明

  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());
        }
    }

上面代码主要说的就是非捕获分组
在这里插入图片描述
代码示例
在这里插入图片描述

02 分组 ()

分组
在这里插入图片描述
捕获分组
在这里插入图片描述

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

在这里插入图片描述
代码示例
在这里插入图片描述
总结
在这里插入图片描述

API

application programming interface
应用程序编程接口

API帮助文档

如何使用帮助文档
在这里插入图片描述

01 字符串

在这里插入图片描述

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 调用方法比较的是字符串值
    }

根据索引返回字符
在这里插入图片描述

02 StringBuilder

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

  • 作用: 提高字符串的操作效率
    在这里插入图片描述
01 构造方法

在这里插入图片描述

02 常用方法

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

03 StringJoiner

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

指定间隔符号以及开始和结束符号
在这里插入图片描述

02 成员方法

在这里插入图片描述
在这里插入图片描述

04 字符串底层原理

字符串存储的内存原理

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

== 号的比较

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

字符串拼接底层原理

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

StringBuilder

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

02 ArrayList–集合

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

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

在这里插入图片描述
基本数据类型对应的包装类 – jdk1.5之后自动转换
在这里插入图片描述

01 ArrayList

在这里插入图片描述

  • <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 成员方法
在这里插入图片描述

03 System

提供一些与系统相关的方法
在这里插入图片描述

04 Runtime

在这里插入图片描述
Runtime 由java给出, 在如下代码中表明, 程序中创建的 Runtime 对象 只能是同一个
在这里插入图片描述
运行cmd命令
如: shutdown -s 默认一分钟后关机
shutdown -s -t 指定多少秒后关机
shutdown -a 取消关机操作
shutdown -r 关机并重启

05 Object

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

在这里插入图片描述
object的clone方法是浅克隆
equals() 在object中是比较地址值, 即直接比较两个变量
在这里插入图片描述

06 Objects

Objects 是一个工具类, 提供了一些操作对象方法供我们使用
在这里插入图片描述

07 BigInteger

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

01 构造方法

在这里插入图片描述
note:

  • 使用静态方法获取 BigInteger 对象, 内部有优化

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

    • 即, 只要进行计算都会产生一个新的 BigInteger 对象

02 成员方法

在这里插入图片描述
BigInteger 是对象, 不能直接进行四则运算

BigInteger 底层存储数据原理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
目前内存扛不住的
在这里插入图片描述

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之间的整数, 多次调用, 返回的是具有相同地址值的同一个对象

成员方法

在这里插入图片描述

09 Date

01 jdk7前时间相关类

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

代码示例
Date
在这里插入图片描述
在这里插入图片描述
SimpleDateFormat

作用:

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

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

在这里插入图片描述
代码示例
在这里插入图片描述
在这里插入图片描述
Calendar
在这里插入图片描述
在这里插入图片描述
note

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

02 jdk8新增时间相关类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

01 ZoneID

在这里插入图片描述

在这里插入图片描述

02 Instant 时间戳

获取一个不带时区的时间, 即标准时区的时间
在这里插入图片描述
代码示例
在这里插入图片描述
在这里插入图片描述

03 ZoneDateTime

在这里插入图片描述
代码示例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

04 DateTimeFormatter

DateTimeFormatter 用于时间的格式化和解析
在这里插入图片描述

05 LocalDate LocalTime LocalDateTime
  • Localdate : 年 月 日
  • LocalTime: 时 分 秒
  • LocalDateTime: 年 月 日 时 分 秒
    在这里插入图片描述
    转换
    在这里插入图片描述
    代码示例
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    LocalTime

在这里插入图片描述
在这里插入图片描述
LocalDateTime
在这里插入图片描述
在这里插入图片描述

06 Duration Period ChronoUnit

在这里插入图片描述
在这里插入图片描述

10 包装类

包装类: 基本数据类型对应的包装类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

以 Integer 为例
这是jdk5以前, 现在直接用就好
在这里插入图片描述
note

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

Integer 成员方法
在这里插入图片描述
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

在这里插入图片描述

插件

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

案例 – 拼图小游戏

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
事件:

  • 事件就是可以被组件识别的操作
  • 当你对组件干了某件事情之后,就会执行对应的代码
  • 三属性
    • 事件源 – 按钮 图片
    • 事件 – 某些操作,鼠标点击等
    • 绑定监听
      在这里插入图片描述
      在这里插入图片描述
      美化界面
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      查看完整图片 A 键
      一键通关 W 键
  1. 整个游戏界面添加键盘事件监听
  2. 编写相应的逻辑代码

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

计数功能

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值