22届社招__希杰
技术栈测试
1、学Java看的哪个资料:
目前在看Java核心技术卷1。Java只知道一些基础语法循环控制结构这样,面向对象也不太懂。
- 重载,重写,泛型懂吗?
-
Java集合这块学过了吗?
-
HashMap源码,JVM,JUC是否看过:
2、数据结构与算法看的哪个资料:
看了郝斌老师视频讲的数据结构,数据结构数组和链表懂一点,其他的就不懂了。
- 链表,栈,队列,二叉树能自己手写吗:
- AVL树,红黑树,线段树学过吗:
- 冒泡,快速,归并排序能手写吗:
- 递归,二分,贪心,回溯,动规,枚举这几种算法学过哪几种:
- LeetCode 大概刷了多少题:
3、框架与中间件
- servlet,cookie,session学过吗:
- SSM学过了吗:
- redis 学过吗:
- SpringBoot项目做过几个:
4、MySQL看的哪些资料:
- sql 熟练吗:
crud知道一点会用一点,其他不会 - 索引底层原理懂吗:
5、计算机基础
这几个课程学校有学过,但是基本上都忘记了。
* 计算机网络看什么资料:
* 操作系统看什么资料:
* 计算机组成原来看的什么资料:
学习规划(2022.7.18)
你的基础,真的太差了,估计即使在工作上做业务,也只是模仿接口写最基本的代码,就像写 Java 基本的逻辑一样,所以我们接下来的首要目标就是:学好 Java + 学好 web,掌握了这些最基本的干活技能,再来学习比较难的八股文和原理。具体安排如下:
1、Java:你对象都不大懂,再学一学 Java基础,从 23 节的对象开始学习就行,然后我每个目录都说了需要掌握什么,你按照我说的最低要求来就行。
2、之后学习下 Java进阶,具体要求如下:
(1)由于你短期内不需要面试的,所以对于集合的源码分析,先不学,学习简单的使用就行。
(2)由于时间原因,你后面还要学习web,所以里面的坦克实战不做。
(3)后面的网络编程,看基本的就行,那个聊天实战不用做,反射也是看几本的就行。
3、学完Java,就重新学习下 web 吧,直接学习 课程大纲 的 ssm,然后学习 springboot,然后做个 SpringBoot电商系统课程说明 的项目。然后你对工作上项目之类的,应该会懂点,之后就回过头来学习算法和八股文这些吧。
另外,学习 ssm 时,如果 Maven 没学过,记得去学习下。课程大纲都有
然后我先不给你安排太多,等你学的差不多,以及根据你的学习速度,再给你安排后面的学习吧。
然后记得来每周打卡学习进度哈,比如像他们这样:23与22届做的比较好的成员示例
有什么问题记得随时私聊帅地
课程大纲: 所有课程大纲入口
每周学习跟进(一个月连续不打打卡会被移出目录)
第一周的打卡学习
时间:2022-07-25—-2022-07-31
视频学习从156-304。
1.从新学习数组,用双重for循环进行二维数组的遍历以及手动编写冒泡排序。冒泡排序一共要进行n-1轮比较(n为数组个数),其中每一轮中要进行n-i次比较(i为第几轮)。
2.面向对象的入门,对象的创建和对象的内存分配机制,其中有栈堆方法区。其中创建对象,对象的变量会在栈中,该变量指向堆中的内存地址,有几个属性就会开辟几个内存空间,其中属性中的字符串常量会指向方法区中的常量池。
3.递归的本质是自己调用自己,然后再依次进行返回,利用递归做了几个递归的小算法,其中经典的有:斐波那契数列和走迷宫。
4.重点掌握了重写和重载,以及区分这两者的区别:
重载发生在本类,方法名必须一样,形参列表中类型、个数或者顺序至少有一个不同,返回值类型和访问修饰符没有要求。
重写发生在父子类,方法名必须一样,形参列表相同,返回值类型要大于等于父类,访问修饰符要小于等于父类。
第二周的打卡学习
时间:2022-08-01—-2022-08-07
视频学习从305-320。
1.多态,父类引用指向子类对象,这就是向上转型。可以调用父类中的所有成员,但是不能调用子类特有的成员。向下转型要求父类的引用必须指向的是当前目标类型的对象, 也就是父类的引用必须强制类型转换成子类类型。
2.instanceOf比较操作符,用于判断对象的运行类型。
3.A aa = new B(),aade 编译类型是A,运行类型是B,aa调用属性是看编译类型,aa调用方法是看运行类型。
4.”=”=和”equals”的区别,”= =”可以判断基本类型,也可以判断引用类型,如果判断基本类型,判断的是值是否相等,如果判断引用类型,判断的是地址是否相等,判断是不是同一个对象。”equals”只能用于判断引用类型。
第三周的打卡学习
时间:2022-08-06—-2022-08-14
视频学习从321-359
1.java中在销毁对象前,会调用该对象的finalize方法,程序员可以在finaize中,写自己的业务逻辑代码(比如释放资源:数据库连接,或者打开文件…),如果程序员不重写finalize,那么就会调用Object类的finalize,即默认处理。
2.垃圾回收机制有自己的GC算法,也可以自己手动运行垃圾回收器System.gc()。
3.学会利用断点调试进行代码的纠错。
4.通过做零钱通和作业的练习,重点对封装继承多态,这一章的内容做了复习。
5.重新复习java的动态绑定机制。当调用对象的方法时,该方法会和对象的内存地址/运行类型绑定;当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用。
第四周的打卡学习
时间:2022-08-15—-2022-08-21
视频学习从360-386
1.当一个方法是static时,就是一个静态方法,可以直接使用类.方法()。
2.如果定义一个变量是一个类变量(静态变量)static,那么该变量最大的特点就是会被XX类的所有对象实例共享,即使没有创建对象实例也可以访问。
3.jdk8之前静态变量是放在方法区中,如果是jdk7以后静态变量是放在堆中,在堆中通过反射机制加载class对象,static在这个类对应的class对象的最后,
4.静态方法,类方法中不允许使用和对象有关的关键字,比如this和super
5.口诀:静态方法只能访问静态成员,
6.类什么是时候被加载:创建对象实例时(new);创建子类对象实例,父类也会被加载,而且父类先被加载,子类后被加载;使用类的静态成员时(静态属性,静态方法)
第五周的打卡学习
时间:2022-08-22—-2022-08-28
视频学习从387-430
1.静态代码块只会执行一次
2.先执行静态属性和静态代码块(哪个在前先执行哪个),在执行普通属性和普通代码块(哪个在前先执行哪个)。
3.继承关系之间静态和普通还有构造的执行顺序:父类的静态代码块和静态属性;子类的静态代码块和静态属性;父类的普通代码块和普通属性初始化;父类的构造方法;子类的普通代码块和普通属性初始化;子类的构造方法。
4.饿汉式和懒汉式的区别:二者最主要的区别在于创建对象的时机不同,饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建;饿汉式不存在线程安全问题,懒汉式存在线程安全问题;饿汉式存在浪费资源的可能,因为如果程序员应该对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题。
5.在jdk7前,接口里的所有方法都没有方法体,即都是抽象方法。jdk8后接口可以有静态方法,默认方法,也就是接口中可以有方法的具体实现(需要使用default关键字修饰)
6.在接口中,抽象方法可以省略abstract关键字
7.解耦比继承更加灵活,继承是满足is -a的关系,而接口只需要满足like -a的关系。
8.类的五大成员:属性、方法、构造器、代码块、内部类
9.定义在外部类的局部位置上(比如方法内):局部内部类(有类名)、匿名内部类(没有类名,重点!!);定义在外部类的成员位置上:成员内部类(没用static修饰)、静态内部类(使用static修饰)
10.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问。
第六周的打卡学习
时间:2022-08-29—-2022-09-04
视频学习从431-510
1.使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而Java是单继承机制。
2.@Retention 指定注解的作用范围。三种SOURCE,CLASS,RUNTIME
3.异常分为两大类,运行时异常和编译时异常。运行时异常,编译器不要求强制处置的异常,编译时异常是编译器要求必须处理的异常。
4.不管是否发生异常,都执行finally代码块。
5.子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常类型的子类型。
6.throw后面是抛出一个具体的异常对象(用来主动抛出异常对象),throws可以抛出多个异常类型(用来处理异常 )。
7.如果i在IntegerCache.low()-128~IntegerCache.higt(127),就直接从数组返回,如果不在-128~127,就直接 new Integer(i)
8.Integer和int类型做判断,有基本数据类型判断的就是值是否相同。如果是Integer和Integer做判断,首先看的是是否在缓存数组中,如果不在就是new出来的对象,两个对象肯定不相同。
9.一个类实现了Serializable(表示类可以串行化:可以在网络传输),类实现了Comparable(表示对象可以比较大小)
10.String是final类不能被其他类继承,不可修改,这边的不可修改不是指的是值不可修改,是指的地址不可修改,单个字符内容是可以变化的
11.String有两种创建方式,一种是直接赋值String s = “hsp”;一种是用构造器String s2 = new String(“hsp”);第一种是先从常量池查看是否有”xxx”数据空间,如果有,直接指向,如果没有则从新创建然后指向,s最终指向的是常量池的空间地址;第二种是先在堆中创建空间,里面维护了value属性,指向常量池的xxx空间,如果常量池中没有”xxx”重新创建,如果有则通过value指向,最终指向的是堆中的空间地址。
12.intern()方法最终返回的是常量池的地址。
13.replace(“”,””)方法执行后,返回的结果才是替换过的,对原来是没有变化的。
14.compareTo方法比较两个字符串大小,如果前者大,则返回正数,后则大,则返回负数,如果相等返回0;如果前面部分都相同,就用前面一个字符的长度减去后面一个字符的长度。
15.String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低;StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,只有当空间不够的时候才扩容更新地址,效率较高。
16.StringBuidler是一个可变的字符序列,此类提供一次与StringBuffer兼容的API,但不保证同步(StringBuidler不是线程安全)。用在字符串缓冲区被当个线程使用。建议优先采用该类,因为在大多数现实中,他比StriungBuffer要快。
17.StringBuilder的方法没有做互斥处理,即没有synchronize锁,因此在单线程的情况下使用StringBuidler。
18.String:不可变字符序列,效率低,但是复用率高;StringBuffer:可变字符序列,效率较高(尤其是增加和删除),线程安全;StringBuilder:可变字符序列,效率最高,线程不安全。效率:StringBuilder>StringBuffer>String
19.如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder;如果字符串存在大量的修改操作,并在单线程的情况下,使用StringBuilder;如果字符串存在大量的修改操作,并在读线程的情况,使用StringBuffer;如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等。
20.DateTimeFormatter是JDK8特有的日期时间类。
21.集合主要是两组,一组是单列集合,一组是双列集合。Collection接口有两个重要的子类,List,Set,他们的实现子类都是单列集合。Map接口的实现子类,是双列集合,存放的是k-v。
22.有些Collection的实现类,可以存放重复的元素,有些不可以。
23.有些Collection的实现类,有些是有序的(List),有些不是有序的(Set)。
24.只要实现了Collection接口的子类,都可以去获取到一个迭代器iterator(),用迭代器来遍历这个集合里的所有元素。
25.增强for就是简化版的iterator()。
26.ArrayList元素可以为null。
27.ArrayList底层是由数组实现。
28.ArrayList是线程不安全(执行效率高)看源码,在多线程情况下,不建议使用ArrayList。
29.ArrayList中维护了一个Object类型的数组,elementData。
30.当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
31.如果使用的指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
第七周的打卡学习
时间:2022-09-05—-2022-09-11
视频学习从511-554
1.ArrayList和Vector的比较:ArrayList线程不安全,效率高,如果有参构造1.5倍,如果无参第一次为10,第二次开始按1.5倍扩容;Vector是线程安全,效率不高,如果是无参默认为10,满后就按2倍扩容,如果指定大小,则每次直接按2倍扩。
1.LinkedList底层实现了双向链表和双端队列特点
2.LinkedList可以添加任意元素(元素可以重复),包括null。
3.LinkedList线程不安全,没有实现同步。
4.LinkeList中维护了两个属性first和last分别指向首节点和尾结点,每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前应该,通过next指向后一个节点,最终实现双向链表。
5.LinkedList的元素的添加和删除、不是通过数组完成的,相对来说效率较高。
6.ArrayList和LinkedList的比较:ArrayList底层是可变数组,增删的效率较低,改查的效率较高;LinkedList底层是双向链表,增删的效率较高,改查的效率较低。如果改查的操作多,选择ArrayList,如果增删的操作多选择LinkedList。
7.Set接口的实现类的对象,不能存放重复的元素,可以添加一个null
8.Set接口对象存放数据是无须的(添加的顺序和取出的顺序不一致),取出的顺序虽然不是添加的顺序,但是他是固定的
9.HashSet底层是HashMap,而HashMao底层是(数组+链表+红黑树)。第一次添加时,table数组扩容到16,临界值(threshold)是16加载因子(loadFactor)是0.75=12;如果table数组使用到了临界值12,就会扩容到162=32,新的临界值就是32*0.75=24,以此类推;在JDK8中,如果一条链表的元素个数到达8,并且table的大小大于等于64就会进行树化(红黑树),否则仍然采用数组扩容机制。
10.HashSet添加的底层实现:根据key得到hash值去计算key应该存放到table表的哪个索引位置并把这个位置的对象赋给p,判断p是否为null,如果p为null表示还没有存放元素,就创建应该Node,就放在该位置 tab i = newNode(hash, key, value, null);如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样并且满足两个条件之一,1)准备加入的key和p指向的Node结点的key是同一个对象,2)p指向的Node结点的key的equals()和准备加入的key比较后相同,就不能加入;再判断p是不是一颗红黑树,如果是一颗红黑树,就调用putTreeVal,来进行添加;如果table对应索引位置已经是一个链表,就使用for循环比较,注意在把元素添加到链表后,立即判断该链表是否已经达到8个结点,如果到达8个节点就调用treeifyBin()对当前这个链表进行树化(转成红黑树),在转成红黑树时,要进行判断,判断条件if (tab = = null || (n = tab.length) A阻塞->因超时释放锁->B加锁->A恢复->释放锁
34.多Redis实例实现分布式锁:Redlock算法,该算法有现成的实现,其Java版本的库为Redisson。
35.Redlock算法实现步骤:获取当前Unix时间,以毫秒为单位;依次尝试从N个实例,使用相同的key和随机值获取锁,并设置响应超时时间。如果服务器没有在规定时间内响应,客户端应该尽快测试另一个Redis实例;客户端使用当前时间减去开始获取锁的时间,得到获取锁使用的时间,当且仅当多数的Redis节点都取到锁,并且使用的时间小于锁失效时间时,锁才算取得成功;如果取到了锁,key的真正有效时间等于有效时间减去获取锁使用的时间;如果获取锁失败,客户端应该再所有的Redis实例上进行解锁。
1.订阅发布模式:角色有发布者,订阅者,代理人;发布者和订阅者之间是完全解耦的关系,他们彼此不知道对方,完全通过代理人来执行事项。
2.观察者模式:角色有观察者,主题;观察者和主题之间是松耦合的关系,他们之间没有代理人。
3.订阅发布模式不等于观察者模式。
4.RocketMQ是纯java编写的开源消息中间件,特点是:高性能、低延迟、分布式事务。
5.RBAC权限控制模型,基于角色的权限控制。
6.FastDFS是开源的轻量级分布式文件系统,用于解决大数据量存储的负载均衡等问题。
7.FastDFS优点:支持HTTP协议传输文件(结合Nginx);对文件内容做Hash处理,节约磁盘空间;支持负载均衡、整合性能较佳。
8.FastDFS的两个角色:跟踪服务器、存储服务器
9.跟踪服务器:主要做调度工作,起到负载均衡的作用。它是客户端和存储服务器交互的枢纽
10.存储服务器:主要提供容量和备份服务,存储服务器是以组为单位,每个组内可以有多台存储服务器,数据互为备份。文件及属性都保存在该服务器上。
第三十三周的打卡学习
时间2023-02-27 —-2023-03-05
视频学习:JVM
1.JVM主要功能:通过ClassLoader寻找和装载class文件;解释字节码称为指令并执行,提供class文件的运行环境;进行运行期间的内存分配和垃圾回收;提供与硬件交互的平台
2.init特殊方法:实例初始化方法,通过JVM的invokespecial指令来调用。
3.clinit特殊方法:类或接口的初始化方法,不包含参数,返回void
4.stack:方法执行时,操作栈的的深度。
9.locals:局部变量所需的存储空间,单位是slot,solt是虚拟机为局部变量分配内存所使用的最小单位。
10.ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增加既有类的功能
11.ASM可以直接产生进制class文件,也可以在类被加载入虚拟机之前动态改变类行为,ASM类文件中读入信息后,能够改变类行为,分析类信息,甚至能根据要求生成新类。
12.目前许多框架入cglib、Hibernat、Spring都直接或间接地使用ASM操作字节码。
13.ASM编程模型:Core Api和Tree Api
14.CoreApi:提供了基于事件形式的编程模型,该模型不需要一次性将整个类的结构读取到内存中,因此这种方式更快,需要更少的内存,但这种编程方式难度较大。
15.TreeApi:提供了基于树形的编程模型,该模型需要一次性将一个类的完整结构全部读取到内存当中,所以这种方法需要更多的内存,这种编程方式较简单。
16.类加载:查找并加载类文件的二进制数据
17.连接:就是将已经读入内存的类的二进制数据合并到JVM运行时环境中去,包含如下几个步骤:1)验证,确保被类的正确性;2)准备,为类的静态变量分配内存,并初始化他们;3)解析,把常量池中的符号引用转换成直接引用
18.初始化:为类的静态变量赋初始值。
19.加载类的方式:最常见的方式,本地文件系统中加载、从jar等归档文件中加载;动态的方式,将java源文件动态编译成class;其他方式,网络下载,从专有数据库中加载等等。
20.Java虚拟机自带的类加载器包括:启动类加载器、平台类加载器、应用程序类加载器。JDK8中有扩展类加载器,之后被平台类加载器取代。
21.JDK8启动类加载器:负责将/lib,或者-Xbootclasspath参数指定的路径中的,且是虚拟机识别的类库加载到内存中
22.JDK8扩展类加载器:负责加载/lib/ext,或者java.ext.dirs系统变量所指定路径中的所有类库。
23.JDK8引用程序类加载器:负责加载classpath路径中的所有类库。
24.Java程序不能直接引用启动类的加载器,直接设置classLoader为null,默认就是使用启动类加载器
25.类加载器并不需要等到某个类“首次主动使用”的时候才加载它,Jvm规范允许类加载器在预料到某个类将要被使用的时候就先预先加载它
26.如果在加载的时候.class文件缺失,会在该类首次主动使用时报告LinkageError错误,如果一直没有被使用,就不会报错
27.JVM中的ClassLoader通常采用双亲委派模型,要求除了启动类加载器外,其余的类加载器都一个有自己的父级加载器,这里的父子关系是组合,而不是继承。
28.双亲委派模型工作过程:一个类加载器接收到类加载请求后,首先搜索它的内建加载器定义的所有“具名模块”;如果找到了合适的模块定义,将会使用该加载器来加载;如果class没有在这些加载器第一的具名模块中找到,那么将会委托给父级加载器,知道启动类加载器;如果父级加载器反馈它不能完成加载请求,比如在它的搜索路径下找不到这个类,那么子的类加载器才自己来加载;在类路径下找到的类将成为这些加载器的无名模块。
29.破坏双亲委派模型:双亲模型有个问题:父类加载器无法向下识别子加载器加载的资源;为了解决这个问题,引入了线程上下文类加载器,可以通过Thread的setContextClassLoader()进行设置。另一种典型情况就是实现热替换,比如OSGI的模块化热部署,它的类加载器就不再是严格按照双亲委派模型,很多可能就在平级的类加载器中执行了。
30.Java程序对类的使用方式分成主动使用和被动使用。
31.JVM必须在每个类或接口“首次主动使用”时才初始化他们;被动使用的类不会导致类的初始化。
32.主动使用的情况:创建类实例;访问某个类或接口的静态变量;调用类的静态方法;反射某个类;初始化某个类的子类,而父类还没有初始化;JVM启动的时候运行的主类;定义了default方法的接口,当接口实现类初始化时
33.当代表一个类的Class对象不再被引用,那么Class对象的生命周期就结束了,对应在方法区中的数据也会被卸载。
34.JVM自带的类加载器的类是不会被卸载的,由用户自定义的类加载器加载的类是可以卸载的。