【Android -- 面试】Android 面试题集锦(Java 基础)

news2024/11/15 23:25:29

在这里插入图片描述

Java 基础

1、Java 的类加载过程

jvm 将 .class 类文件信息加载到内存并解析成对应的 class 对象的过程,

注意:jvm 并不是一开始就把所有的类加载进内存中,只是在第一次遇到某个需要运行的类才会加载,并且只加载一次

主要分为三部分:1、加载,2、链接(1.验证,2.准备,3.解析),3、初始化

  • 加载
    类加载器包括 BootClassLoaderExtClassLoaderAPPClassLoader

  • 链接

    • 验证:(验证 class 文件的字节流是否符合 jvm 规范)
    • 准备:为类变量分配内存,并且进行赋初值
    • 解析:将常量池里面的符号引用(变量名)替换成直接引用(内存地址)过程,在解析阶段,jvm 会把所有的类名、方法名、字段名、这些符号引用替换成具体的内存地址或者偏移量。
  • 初始化
    主要对类变量进行初始化,执行类构造器的过程,换句话说,只对 static 修试的变量或者语句进行初始化。
    示例:Person person = new Person(); 为例进行说明。

Java 编程思想中的类的初始化过程主要有以下几点:

  • 找到class文件,将它加载到内存
  • 在堆内存中分配内存地址
  • 初始化
  • 将堆内存地址指给栈内存中的 p 变量

2、String、StringBuilder、StringBuffer

StringBuffer 里面的很多方法添加了 synchronized 关键字,是可以表征线程安全的,所以多线程情况下使用它。

执行速度:

StringBuilder > StringBuffer > String

StringBuilder 牺牲了性能来换取速度的,这两个是可以直接在原对象上面进行修改,省去了创建新对象和回收老对象的过程,而 String 是字符串常量(final)修试,另外两个是字符串变量,常量对象一旦创建就不可以修改,变量是可以进行修改的,所以对于String字符串的操作包含下面三个步骤:

  1. 创建一个新对象,名字和原来的一样
  2. 在新对象上面进行修改
  3. 原对象被垃圾回收掉

3、JVM 内存结构

Java 对象实例化过程中,主要使用到虚拟机栈、Java 堆和方法区。Java 文件经过编译之后首先会被加载到 jvm 方法区中,jvm 方法区中很重的一个部分是运行时常量池,用以存储 class 文件类的版本、字段、方法、接口等描述信息和编译期间的常量和静态常量。

3.1 JVM 基本结构
类加载器 classLoader,在 JVM 启动时或者类运行时将需要的 .class 文件加载到内存中。执行引擎,负责执行 class 文件中包含的字节码指令。本地方法接口,主要是调用 C/C++ 实现的本地方法及返回结果。内存区域(运行时数据区),是在JVM运行的时候操作所分配的内存区,主要分为以下五个部分,如下图:
在这里插入图片描述

  • 方法区:用于存储类结构信息的地方,包括常量池、静态变量、构造函数等。
  • Java堆(heap):存储Java实例或者对象的地方。这块是gc的主要区域。
  • Java栈(stack):Java 栈总是和线程关联的,每当创建一个线程时,JVM 就会为这个线程创建一个对应的 Java 栈。在这个 java 栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。所以 java 栈是线程私有的。
  • 程序计数器:用于保存当前线程执行的内存地址,由于 JVM 是多线程执行的,所以为了保证线程切换回来后还能恢复到原先状态,就需要一个独立的计数器,记录之前中断的地方,可见程序计数器也是线程私有的。
  • 本地方法栈:和 Java 栈的作用差不多,只不过是为 JVM 使用到的 native 方法服务的。

3.2 JVM 源码分析

  • JVM 源码分析

4、GC 机制

垃圾收集器一般完成两件事:

  • 检测出垃圾;
  • 回收垃圾;

4.1 Java 对象引用
通常,Java 对象的引用可以分为4类:强引用、软引用、弱引用和虚引用。

  • 强引用:通常可以认为是通过new出来的对象,即使内存不足,GC进行垃圾收集的时候也不会主动回收。
Object obj = new Object();
  • 软引用:在内存不足的时候,GC进行垃圾收集的时候会被GC回收。
Object obj = new Object();
SoftReference<Object> softReference = new SoftReference<>(obj);
  • 弱引用:无论内存是否充足,GC进行垃圾收集的时候都会回收。
Object obj = new Object();
WeakReference<Object> weakReference = new WeakReference<>(obj);
  • 虚引用:和弱引用类似,主要区别在于虚引用必须和引用队列一起使用。
Object obj = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> phantomReference = new PhantomReference<>(obj, referenceQueue);
  • 引用队列:如果软引用和弱引用被GC回收,JVM就会把这个引用加到引用队列里,如果是虚引用,在回收前就会被加到引用队列里。

垃圾检测方法

  • 引用计数法:给每个对象添加引用计数器,每个地方引用它,计数器就+1,失效时-1。如果两个对象互相引用时,就导致无法回收。
  • 可达性分析算法:以根集对象为起始点进行搜索,如果对象不可达的话就是垃圾对象。根集(Java栈中引用的对象、方法区中常量池中引用的对象、本地方法中引用的对象等。JVM在垃圾回收的时候,会检查堆中所有对象是否被这些根集对象引用,不能够被引用的对象就会被垃圾回收器回收。)

垃圾回收算法:

  • 标记-清除
    标记:首先标记所有需要回收的对象,在标记完成之后统计回收所有被标记的对象,它的标记过程即为上面的可达性分析算法。
    清除:清除所有被标记的对象
    缺点:效率不足,标记和清除效率都不高
    空间问题,标记清除之后会产生大量不连续的内存碎片,导致大对象分配无法找到足够的空间,提前进行垃圾回收。

  • 复制回收算法
    将可用的内存按容量划分为大小相等的2块,每次只用一块,当这一块的内存用完了,就将存活的对象复制到另外一块上面,然后把已使用过的内存空间一次清理掉。
    缺点
    将内存缩小了原本的一般,代价比较高
    大部分对象是“朝生夕灭”的,所以不必按照1:1的比例划分。
    现在商业虚拟机采用这种算法回收新生代,但不是按1:1的比例,而是将内存区域划分为eden 空间、from 空间、to 空间 3 个部分。
    其中 from 空间和 to 空间可以视为用于复制的两块大小相同、地位相等,且可进行角色互换的空间块。from 和 to 空间也称为 survivor 空间,即幸存者空间,用于存放未被回收的对象。
    在垃圾回收时,eden 空间中的存活对象会被复制到未使用的 survivor 空间中 (假设是 to),正在使用的 survivor 空间 (假设是 from) 中的年轻对象也会被复制到 to 空间中 (大对象,或者老年对象会直接进入老年带,如果 to 空间已满,则对象也会直接进入老年代)。此时,eden 空间和 from 空间中的剩余对象就是垃圾对象,可以直接清空,to 空间则存放此次回收后的存活对象。这种改进的复制算法既保证了空间的连续性,又避免了大量的内存空间浪费。

  • 标记-整理
    在老年代的对象大都是存活对象,复制算法在对象存活率教高的时候,效率就会变得比较低。根据老年代的特点,有人提出了“标记-压缩算法(Mark-Compact)”
    标记过程与标记-清除的标记一样,但后续不是对可回收对象进行清理,而是让所有的对象都向一端移动,然后直接清理掉端边界以外的内存。
    这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。

  • 分带收集算法
    根据对象存活的周期不同将内存划分为几块,一般是把Java堆分为老年代和新生代,这样根据各个年代的特点采用适当的收集算法。
    新生代每次收集都有大量对象死去,只有少量存活,那就选用复制算法,复制的对象数较少就可完成收集。
    老年代对象存活率高,使用标记-压缩算法,以提高垃圾回收效率。

5、类加载器

程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是根据程序的需要,通过Java的类加载机制(ClassLoader)来动态加载某个class文件到内存当中的,从而只有 class 文件被载入到了内存之后,才能被其它class所引用。所以 ClassLoader 就是用来动态加载class文件到内存当中用的。

5.1 双亲委派原理
每个 ClassLoader 实例都有一个父类加载器的引用(不是继承关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但是可以用做其他 ClassLoader 实例的父类加载器。
当一个 ClassLoader 实例需要加载某个类时,它会试图在亲自搜索这个类之前先把这个任务委托给它的父类加载器,这个过程是由上而下依次检查的,首先由顶层的类加载器Bootstrap CLassLoader进行加载,如果没有加载到,则把任务转交给Extension CLassLoader视图加载,如果也没有找到,则转交给AppCLassLoader进行加载,还是没有的话,则交给委托的发起者,由它到指定的文件系统或者网络等 URL 中进行加载类。还没有找到的话,则会抛出CLassNotFoundException异常。否则将这个类生成一个类的定义,并将它加载到内存中,最后返回这个类在内存中的 Class 实例对象。

5.2 为什么使用双亲委托模型
JVM在判断两个class是否相同时,不仅要判断两个类名是否相同,还要判断是否是同一个类加载器加载的。
避免重复加载,父类已经加载了,则子CLassLoader没有必要再次加载。
考虑安全因素,假设自定义一个String类,除非改变JDK中CLassLoader的搜索类的默认算法,否则用户自定义的CLassLoader如法加载一个自己写的String类,因为String类在启动时就被引导类加载器 Bootstrap CLassLoader加载了。

6、集合

Java集合类主要由两个接口派生出:Collection 和 Map,这两个接口是Java集合的根接口。

Collection 接口是集合类的根接口,Java 中没有提供这个接口的直接的实现类。但是却让其被继承产生了两个接口,就是 Set 和List。Set中不能包含重复的元素。List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。

Map 是 Java.util 包中的另一个接口,它和 Collection 接口没有关系,是相互独立的,但是都属于集合类的一部分。Map 包含了 key-value 对。Map不能包含重复的key,但是可以包含相同的value。

6.1 区别
List,Set 都是继承自Collection接口,Map 则不是;
List 特点:元素有放入顺序,元素可重复; Set 特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法;
LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
HashMap是非线程安全的,HashTable是线程安全的;

6.2、List 和 Vector 比较
Vector 是多线程安全的,线程安全就是说多线程访问同一代码,不会产生不确定的结果。而 ArrayList 不是,这个可以从源码中看出,Vector 类中的方法很多有 synchronized 进行修饰,这样就导致了Vector在效率上无法与 ArrayList 相比;
两个都是采用的线性连续空间存储元素,但是当空间不足的时候,两个类的增加方式是不同。
Vector 可以设置增长因子,而 ArrayList 不可以。
Vector 是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用。

6.3、HashSet如何保证不重复
HashSet 底层通过 HashMap 来实现的,在往 HashSet 中添加元素是

public boolean add(E e) {
return map.put(e, PRESENT)==null;
}


// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

在 HashMap 中进行查找是否存在这个 key,value 始终是一样的,主要有以下几种情况:

  • 如果 hash 码值不相同,说明是一个新元素,存;
  • 如果 hash 码值相同,且 equles 判断相等,说明元素已经存在,不存;
  • 如果 hash 码值相同,且 equles 判断不相等,说明元素不存在,存;
  • 如果有元素和传入对象的 hash 值相等,那么,继续进行 equles() 判断,如果仍然相等,那么就认为传入元素已经存在,不再添加,结束,否则仍然添加;

6.4 HashSet 与 Treeset 的适用场景

  • HashSet 是基于Hash算法实现的,其性能通常都优于 TreeSet。为快速查找而设计的 Set ,我们通常都应该使用 HashSet ,在我们需要排序的功能时,我们才使用 TreeSet 。
  • TreeSet 是二叉树(红黑树的树据结构)实现的,Treeset 中的数据是自动排好序的,不允许放入 null 值
  • HashSet 是哈希表实现的,HashSet 中的数据是无序的,可以放入 null,但只能放入一个 null,两者中的值都不能重复,就如数据库中唯一约束。
  • HashSet 是基于 Hash 算法实现的,其性能通常都优于 TreeSet。为快速查找而设计的 Set,我们通常都应该使用 HashSet,在我们需要排序的功能时,我们才使用 TreeSet。

6.5 HashMap与TreeMap、HashTable的区别及适用场景
HashMap 非线程安全,基于哈希表(散列表)实现。使用HashMap要求添加的键类明确定义了 hashCode() 和 equals() [可以重写hashCode()和equals()],为了优化 HashMap 空间的使用,您可以调优初始容量和负载因子。其中散列表的冲突处理主要分两种,一种是开放定址法,另一种是链表法。HashMap的实现中采用的是链表法。
TreeMap :非线程安全基于红黑树实现,TreeMap 没有调优选项,因为该树总处于平衡状态

7、 常量池

7.1 Interger 中的128(-128~127)
当数值范围为-128~127时:如果两个new出来Integer对象,即使值相同,通过“ == ”比较结果为false,但两个对象直接赋值,则通过“ == ”比较结果为“true,这一点与String非常相似。当数值不在-128~127时,无论通过哪种方式,即使两个对象的值相等,通过“ == ”比较,其结果为false;当一个Integer对象直接与一个int基本数据类型通过“ == ”比较,其结果与第一点相同;Integer对象的hash值为数值本身;

@Override
public int hashCode() {
return Integer.hashCode(value);
}

7.2 为什么是 -128 ~ 127?
在 Integer 类中有一个静态内部类 IntegerCache,在 IntegerCache 类中有一个 Integer 数组,用以缓存当数值范围为 -128~127 时的 Integer 对象。

8、泛型

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

它提供了编译期的类型安全,确保你只能把正确类型的对象放入 集合中,避免了在运行时出现ClassCastException

使用Java的泛型时应注意以下几点:

  • 泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
  • 同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
  • 泛型的类型参数可以有多个。
  • 泛型的参数类型可以使用extends语句,例如。习惯上称为“有界类型”。
  • 泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName("java.lang.String");

8.1 T泛型和通配符泛型

  • ? 表示不确定的java类型。
  • T 表示java类型。
  • K V 分别代表java键值中的Key Value。
  • E 代表Element。

8.2 泛型擦除
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。

泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如 List在运行时仅用一个List来表示。这样做的目的,是确保能和Java 5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。

8.3 限定通配符
一种是<? extends T>它通过确保类型必须是T的子类来设定类型的上界,
另一种是<? super T>它通过确保类型必须是T的父类来设定类型的下界。
另一方面表 示了非限定通配符,因为可以用任意类型来替代。
例如List<? extends Number>可以接受List或List。

8.4 泛型面试题
你可以把List传递给一个接受List参数的方法吗?

对任何一个不太熟悉泛型的人来说,这个Java泛型题目看起来令人疑惑,因为乍看起来String是一种Object,所以
List应当可以用在需要List的地方,但是事实并非如此。真这样做的话会导致编译错误。如
果你再深一步考虑,你会发现Java这样做是有意义的,因为List可以存储任何类型的对象包括String,
Integer等等,而List却只能用来存储Strings。

Array中可以用泛型吗?

Array 事实上并不支持泛型,这也是为什么Joshua Bloch在Effective
Java 一书中建议使用List来代替Array,因为List可以提供编译期的类型安全保证,而Array却不能。

9、反射

9.1 概念

JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

9.2 作用
Java 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

推荐阅读

  • Android 面试之必问Java基础

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ARMv8 SIMD和浮点指令编程】NEON 比较指令——比较的方方面面

比较指令是常见的一类指令,NEON 中当然也排除,下面涉及比较和测试位两类指令。 1 CMEQ (register) 按位比较相等(向量)。该指令将第一个源 SIMD&FP 寄存器中的每个向量元素与第二个源 SIMD&FP 寄存器中的相应向量元素进行比较,如果比较相等,则将目标 SIMD&…

基于Python+Django+mysql+html通讯录管理系统

基于PythonDjangomysqlhtml通讯录管理系统 一、系统介绍二、功能展示1.用户登陆2.用户注册3.密码修改4.查询5.添加6.修改7.删除 三、其它系统四、获取源码 一、系统介绍 该系统实现了 用户登陆、用户注册、密码修改、查询信息、添加信息&#xff0c;修改信息、删除信息 运行环…

vue2脚手架可视化小项目

vue2脚手架小项目 这个项目又数据可视化可以通过点击按钮修改数据&#xff0c;同时图形的内容也会随着变化这里面也又保存功能&#xff0c;搜索功能&#xff0c;添加功能用到的框架有vue2脚手架&#xff0c;语言有bootstrap&#xff0c;css&#xff0c;也用了echarts 下面会先…

从Web2.0走向Web3.0还有多远?

Web2.0时代给互联网带来了巨大的变革&#xff0c;让用户成为内容的创造者和共享者。然而&#xff0c;随着技术的不断发展和创新&#xff0c;我们正在逐渐迈向Web3.0时代&#xff0c;这将是一个更加去中心化、透明和安全的数字世界。那么&#xff0c;从Web2.0走向Web3.0还有多远…

202322读书笔记|《给你一个大抱抱:治愈系暖心绘本》——如果事与愿违,请相信一切自由安排

&#xff3b;TOC&#xff3d;(202322读书笔记&#xff5c;《给你一个大抱抱&#xff1a;治愈系暖心绘本》——如果事与愿违&#xff0c;请相信一切自由安排 作者白开水DAWAN&#xff0c;治愈系小说&#xff0c;画面明媚有趣轻松&#x1f92a;&#x1f92a;&#x1f618;&#…

learn C++ NO.10——string(3)

引言&#xff1a; 现在是北京时间2023年6月22日的早上8点。又是一年端午&#xff0c;时光如梭。这一年来发生的变化太多了&#xff0c;遥想去年此时&#xff0c;我还沉浸在被大学录取的喜悦中&#xff0c;转眼间大一就过去了。这里我也衷心的祝愿您和您的家人端午安康&#xf…

Triton教程 --- 自定义操作

Triton教程 — 自定义操作 Triton系列教程: 快速开始利用Triton部署你自己的模型Triton架构模型仓库存储代理模型设置优化动态批处理速率限制器模型管理 自定义操作 Triton 推理服务器部分支持允许自定义操作的建模框架。 自定义操作可以在构建时或启动时添加到 Triton&…

前端3D Three.js 在本地搭建一个官方网站

上文Web前端 3D开发入门规划 3D效果将不再是桌面应用的专利我们说了说 WEB 3D的一个发展和学习方向 那么 我们还是先搞定文档使用的问题 我们可以访问http://www.yanhuangxueyuan.com/Three.js/这里面可以查到使用方法 但不是最新的 而是别人用官方文档改的 真正的官方文档地址…

30 linux 新建进程的进程号是如何分配的?

前言 呵呵 进程号是我们经常使用到的, 但是 却从来 没有深究过的东西 这里 就来看一下 具体的进程号的生成方式 linux 新建进程是以 fork exec 的形式创建进程的 子进程 是 复制自 父进程 pid 是怎么生成的? 分配 pid 的地方调用堆栈如下, fork 之后, 会为 新进程 申…

全志V3S嵌入式驱动开发(基于usb otg的spi-nand镜像烧入)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过spi nand驱动&#xff0c;但是这个驱动是建立在linux系统从sd卡加载的情况下进行的。开发测试的情况下&#xff0c;这么做或许是可以的…

PWM详解(嵌入式学习)

这里写目录标题 前言定义参数工作原理应用练习 前言 在STM32微控制器中&#xff0c;PWM代表脉冲宽度调制&#xff08;Pulse Width Modulation&#xff09;。PWM是一种用于控制电子设备的技术&#xff0c;通过调整信号的脉冲宽度和周期&#xff0c;可以模拟出不同的电压或功率级…

【python】—— 基础语法(一)

序言&#xff1a; 在之前&#xff0c;我们已经对【python】的开发环境进行了相应的安装&#xff0c;紧接着本期我就讲给大家介绍它的相关语法。对于学过【C/C】或者其他语言的小伙伴来说&#xff0c;语法内容学习起来就会掌握的很快了。 目录 前言 &#xff08;一&#xff0…

【架构师】零基础到精通——网关策略

博客昵称&#xff1a;架构师Cool 最喜欢的座右铭&#xff1a;一以贯之的努力&#xff0c;不得懈怠的人生。 作者简介&#xff1a;一名退役Coder&#xff0c;软件设计师/鸿蒙高级工程师认证&#xff0c;在备战高级架构师/系统分析师&#xff0c;欢迎关注小弟&#xff01; 博主小…

vue服务端渲染SSR

一&#xff1a;ssr的理解 1、服务端渲染 Server Side Render SSR解决方案&#xff0c;后端渲染出完整的首屏的dom结构返回&#xff0c;前端拿到的内容包括首屏及完整spa结构&#xff0c;应用激活后依然按照spa方式运行&#xff0c;这种页面渲染方式被称为服务端渲染 (server si…

ISO C++ 26 并发和并行性重大完善

ISO C 委员会举行会议正式通过了 C 26 的时间表。ISO C 标准委员会主席兼微软语言架构师 Herb Sutte&#xff0c;并发和并行小组仍在按计划推进 C26 的 std::execution 和 SIMD 并行 一、 C23 与C 26 开发时间表&#xff1a; 二、C26标准属性三大规则。非正式总结是: [已经在c …

【Python 基础篇】Python数据序列推导式

文章目录 前言一、列表推导式二、字典推导式三、集合推导式总结 前言 在Python中&#xff0c;推导式&#xff08;Comprehension&#xff09;是一种简洁而强大的语法&#xff0c;用于快速创建列表、字典和集合。推导式使得在一个简单的语句中就能生成一个新的数据结构&#xff…

忘记Gmail谷歌账号密码或者密码错误怎么办?用这种方法轻松搞定

有些朋友以前注册过谷歌邮箱&#xff0c;但很久很久没有再去使用。现在注册ChatGPT需要谷歌邮箱&#xff0c;于是打算把尘封已久的谷歌邮箱找出来&#xff0c;可是这时候你突然发现&#xff0c;谷歌邮箱的密码忘了。 今天重点来说说如何找回谷歌账号的密码&#xff0c;希望能够…

英语口语进阶:让你的疲劳与口渴表达更地道

前言 &#x1f3e0;个人主页&#xff1a;我是沐风晓月 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是沐风晓月&#xff0c;阿里云社区博客专家 &#x1f609;&#x1f609; &#x1f495; 座右铭&#xff1a; 先努力成长自己&#xff0c;再帮助更多的人,一起加油进…

Web网页制作期末复习(4)——CSS盒子模型、弹性盒模型(flex box)、文档流、浮动、清除浮动、定位、圆角、阴影

目录 CSS盒子模型 概念 弹性盒模型&#xff08;flex box&#xff09; 内容 父元素上的属性 display属性 flex-direction属性 justify-content属性 align-items属性 子元素上的属性 flex 文档流&#xff08;标准流&#xff09; 浮动 定义 浮动的原理 清除浮动 …

用OpenCV进行OCR字符分割

1. 引言 本文重点介绍如何利用传统的图像处理的方法来进行OCR字符切分&#xff0c;进而可以用分割后的单个字符做相应的后续任务&#xff0c;虽然现在计算机视觉依然是卷积神经网络的天下&#xff0c;但是对于一些相对简单的落地场景传统方案还是很有效的。 闲话少说&#xff…