2027届_怀瑾

技术栈测试

1、学Java看的哪个资料:学校的资料

  • 重载,重写,泛型懂吗?前两个学过但是忘了
  • Java集合这块学过了吗?
  • HashMap源码,JVM,JUC是否看过:

2、数据结构与算法看的哪个资料: 学校的资料

  • 链表,栈,队列,二叉树能自己手写吗: 学过但是不扎实
  • AVL树,红黑树,线段树学过吗:
  • 冒泡,快速,归并排序能手写吗: 学过
  • 递归,二分,贪心,回溯,动规,枚举这几种算法学过哪几种: 学过前两个
  • LeetCode 大概刷了多少题: 123道,断断续续的来回刷,但是每次都会忘记

3、框架与中间件

  • servlet,cookie,session学过吗:
  • SSM学过了吗:
  • redis 学过吗:
  • SpringBoot项目做过几个:

4、MySQL看的哪些资料:学校的资料
– sql 熟练吗: **leetcode关于sql初始的题刷过33道,但是忘了
– 索引底层原理懂吗:

5、计算机基础

  • 计算机网络看什么资料:学校的书籍(计算机网络谢希仁第八版)
  • 操作系统看什么资料:学校的书籍
  • 计算机组成原来看的什么资料:学校的书籍

学习规划

一些链接入口

课程大纲: 所有课程大纲入口 ,PS:你要的东西,课程大纲基本都会有哈,需要学啥记得来课程大纲看看。

你的大致情况分析与规划

首先你拥有的时间非常多,但是你的目标其实不是很明确,不过帅地作为过来人,先帮你铺垫一下以后工作相关的东西,未来无论你是要去银行国企,去开发岗,去数据分析,去卷大厂,都来得及。

也就是说,平时学业上你就跟着学业,业余时间想学什么可以和我商量,然后挪出一部分时间,来学习我这边安排的内容。

近期总体规划:语言上选择 Java + Python,就是Python你应该会经常用到,但是得深入掌握一门开发语言,一般就是C++,Go,Java,这里推荐Java,可以干的事情多。

未来一年目标:跟着刷算法,学习 Java,跟着做一些项目,以及过一过核心八股文原理。

研0阶段具体学习计划安排(2023.10.10)

接下来系统学习一下各方面内容

1、Java理论:学校的Java讲的太浅了,咱们学深入一点,直接学习Java基础 ,懂的跳过即可,然后学习 Java进阶吧,Java进阶那里,源码分析有点难,可以跳过哈,问题不大的,。

划重点:为了学习更快,请学习的时候,按照我网站的说明来,每个目录都会说明需要掌握哪些,该跳过的就跳过哈,按照最低的要求来学就行项目实战可以做一下哦

配套练习(必做比做):你学到对应模块的时候,可以在牛客网这里刷刷题:Java语法刷题,相当于熟悉一下基本语法。视频的练习你可做可不做,但是这个配套练习必须做哈。

时间安排:这个课程比较系统和深入,推荐 2 个月完成。

2、刷算法:就按照 我这个课程刷就行:拿捏算法面试课程,这个可以好好刷一下,无论哪个岗位都会考察。

时间推荐:每周 10+题。

3、做一做项目:学完 1之后,你可以直接跟着这个路线学:web学习路线整合(框架+项目),做一做项目,就是先过一下技术栈,后面你想做其他的,也方便你做抉择。

时间推荐:推荐去读研之前,把这些过一遍吧,这样有个大概的认知。

学习顺序

学习顺序:两条线学,1=》3一条线,2是一条线。

就行先安排这么多,然后记得来每周打卡学习进度哈,也可以星球每天打卡哦,我会看的,比如像他们这样:0. 每周打卡做的比较好的成员示例,你也可以每天打卡或者星球打卡吧,我会看的

有什么问题记得随时私聊帅地

每周学习记录

2023.10.18 这一个周看了Java基础4节视频并做了总结,按顺序依次刷了10道算法题,将其算法思想以及时空复杂度也做了总结。因为有三个大的课程设计作业需要完成,所以这周完成的内容较少,下一个周会全身心投入计划当中。
2023.11.2 打算先以毕业论文为主,目前在大佬的指导下正在调研;计划两周看完Java基础后,完成一个Web项目(赶上同一起跑线上的同学的步伐)。
2024.11.13

break、continue、return

  1. break结束外层循环,开始执行循环之后的代码;
  2. continue跳过本次循环,接着开始下一次循环;
  3. return 退出所在方法;

数组

// 创建 赋值
int[] arr1 = {7, 5, 6};
// 未赋值
int[] arr2 = new int[3];

数组在创建后就不能修改大小

long[] arr = new long[10];
arr = new long[25]; //arr在栈区先指向一个大小为10的内存空间,后指向重新创建的一个大小为20的内存空间

排序

冒泡排序
// 遍历数组的过程中将当前顺序下的最大值调换至末尾;
// 外层循环每执行一次说明数组需要排序的次数减一

int[] arr = {3, 1, 4, 9, 2};
for(int i = 0; i < arr.length - 1; i++){
    for(int j = 0; j < arr.length - i; j++){
        if(arr[i] > arr[i+1]){
            int temp = arr[i+1];
            arr[i+1] = arr[i];
            arr[i] = temp;
        }
    }
}

11.14

类与对象

关系

类:涵盖对象的所有属性和行为(方法)

对象:具体实例

内存分配

内存布局

  1. 类的具体实例(对象)存储在栈,属性中基本数据类型的内存分配在堆;引用类型(如字符串)的数据空间内存实际存储在方法区的常量池中,其地址存储在堆。

  2. 对象被创建时,就会在方法区加载其属性和行为信息

方法

调用机制

主函数存储在栈空间,当执行到方法时,就会在栈中开辟一个独立空间:基本数据类型采用值拷贝传递。当方法执行到return语句时返回到主函数调用方法的地方,继续执行之后的语句。

传参机制

场景:主函数中调用一个交换基本数据类型的函数,主函数中的基本数据类型值不变。

形参的任何改变不会影响到实参

12.9

克隆

浅克隆与深克隆的区别

浅克隆:拷贝了原来的对象中的变量,但是仍然存在引用变量是同一个并未独立的关联;

深克隆:新对象和原来的对象是两个独立的对象,只是属性相同。

递归

// 阶乘
public int fac(int n){
    if(n == 1){
        return 1;
    }
    else return fac(n - 1) * n;
}
//斐波那契求和
public int fibo(int n){
    if(n == 1 || n == 2){
        return 1;
    }
    else {
        return fibo(n - 1) + fibo(n - 2);
    }
}
public static void main(String[] args) {
    int sum =0;
    for(int i = 1; i <= n; i++){
        sum += fibo(n);
    }
    printf("fibo前n项的和为:"+sum);
    return 0;
}

方法重载

方法名称可以相同但要求形参列表不一致。

可变参数

是为了简化同名同功能仅参数个数不同的方法设置的。

public int varparameters(int length, int... nums); 
// nums的本质数组;
// 其中形参列表只能出现一个可变参数;
// 可变参数可以和普通类型的参数一起放在形参列表,但可变参数需要放在末尾

作用域

全局变量和局部变量的区别

  1. 全局变量(属性)有默认值,可以不赋值直接使用;
  2. 局部变量没有默认值,必须先赋值再使用。
  3. 全局变量(属性)可以加修饰符;局部变量不可以。

变量的作用范围

  1. 局部变量和全局变量重名时,遵循就近原则;
  2. 全局变量通过对象调用既能被本类使用,又能被其他类使用;
  3. 局部变量只能在本类中对应的方法中使用;

变量的生命周期

  1. 全局变量(属性)生命周期随着对象的创建而创建,随着对象的销毁而销毁;
  2. 局部变量生命周期在一次方法的调用过程中创建、销毁。

构造器

作用

在创建对象时,系统会自动调用构造器完成对新对象的初始化

class Person{
    String name;
    int age;
    public Person(String name, int age){ // 与类名同名
    this.name = name;
    this.age = age;
    }
}

this

含义

对象调用构造器时this就代表该对象的全局变量(属性),与局部变量区分开来。

1.9

this和super的比较

  1. this访问本类的属性和方法,若本类没有则从父类中继续查找;super访问父类中的属性和方法;
  2. this调用本类的构造器,super调用父类的构造器,二者都必须放在构造器的首行;
  3. this表示当前对象;super是在子类中访问父类对象。

作用

  1. 区分相同名字的类
  2. 控制访问范围
  3. 便于管理类

封装

定义:将属性设置为私有,只能通过内部定义的getter和setter方法来获取

继承

定义:当多个类(子类)中存在相同属性和方法时,将这些提出到单独的一个类(父类)中,子类只需extends(继承)父类即可,无需定义

多态

定义:

方法的多态:即重写和重载;

对象的多态:同一个方法,使用不同的对象来执行不同的操作。

Animal animal = new Dog();//编译类型不可改变,为Animal
animal.cry();
Animal animal = new Cat();//运行类型可以改变,用以实现多态
animal.cry();

​ 注意:

  1. 向上转型:多态在遵守访问权限的情况下,可以调用父类的所有成员,但不能调用子类的特有的成员(过不了编译阶段,因为在编译阶段,能调用哪些成员,是由编译类型来决定的)。
  2. 向下转型:
// 子类类型 引用名 = (子类类型) 父类引用;
Cat cat = (Cat) animal; // 向下强转后,此时对象可以调用特有的成员

属性的多态:属性没有“重写”,其值只跟编译类型有关

instanceof //判断运行类型是否是该类或该类的子类

面向对象的三大特性

封装、继承、多态

和equals的对比

  1. 可判断基本类型的值是否相等,也可判断引用类型是否是同一个对象
  2. equals 只能判断引用类型

equals和HashCode的对比

  1. HashCode只需利用公式将内存地址转换为一个hash值就能比较,效率较高,但不完全可靠(不同对象生成的hashcode可能会重复);
  2. equals在HashCode判断为true后作进一步判断来使用

讲一下equals()与hashcode(),什么时候重写,为什么重写,怎么重写?

2025.2.25

类变量

int count = 0; //实例变量,对象独享
public static count = 0; //类变量(静态变量),对象共享

类方法

注意事项

  1. 不允许使用和对象有关的关键字,比如this和super;
  2. 只能访问静态变量/方法
  3. 普通变量/方法只能通过对象来访问

代码块

定义

​ 可以对构造器进行初始化,后执行构造器的内容,但优先级低于super();

public class Code {
    public static void main(String[] args){
        Hi hi = new Hi("你好");  // 每创建一个对象就执行一次代码块
    }
}
class Hi {
    private String name;
}
{
    System.out.println("didadida");
}
public Hi(String name){
    System.out.println("判断代码块是否可以先对构造器进行初始化");
    this.name = name;
}

单例模式

饿汉式步骤

  1. 私有化构造器
  2. **随着类的加载,在其内部创建一个static对象 **
  3. 提供一个public的static方法,返回static对象

懒汉式

​ 只有当用户使用getInstance时才创建并返回static对象,后面再次调用时会返回首次创建的static对象,从而保证单例模式。

final

注意事项

  1. 可重新赋值的位置有:定义时、代码块中、构造器中
  2. 若final修饰的是静态属性,那么初始化的位置只能是前两个,
  3. final + static 搭配创建对象,可以避开类的加载

抽象类abstract

出现原因

​ 方便设计者后续对没有实现的方法

(抽象方法)进行实现

注意事项

  1. 不能被实例化,即不能创建对象;
  2. 不一定要包含abstract方法;
  3. 一旦类中包含了abstract方法,该类必须被声明为abstract;
  4. 只能用于修饰类和方法;
  5. 方法被abstract修饰后,不能被实现;
  6. 当一个类继承了abstract类,则必须实现所有abstract方法,除非该类也声明为abstract类

9、抽象类和接口的区别;

11、抽象方法能不能加final;

接口

可包含

  1. 抽象方法
  2. 默认实现方法
  3. 静态方法

alt+enter 快捷实现普通类实现接口所有public方法(抽象)

细节

  1. 一个类可以实现多个接口
  2. 接口中的属性只能是final,而且是 public static final 修饰符
  3. 接口不能继承类,但是可以继承多个接口
  4. 接口的修饰符只能是public 和 默认, 这点和类的修饰符是一样的(???)
  5. 具有多态特性

接口与继承的比较

1. 继承是为了解决代码的复用性和可维护性,子类继承后,就可拥有父类的功能;
1. 接口是设计好各种抽象方法,便于让其他类去实现,更加灵活;是对单继承机制的一种补充。

内部类

局部内部类

细节
  1. 是定义在外部类的局部(如方法中),因此可以直接访问外部类的所有成员;
  2. 不能添加访问修饰符,因为其类似于局部变量,但可以用final修饰(不可被继承);
  3. 作用域仅在定义局部内部类的方法或代码块中(???)
  4. 如果外部类和局部内部类的成员重名时,访问时默认遵循就近原则,如果想访问外部类的成员,可以使用外部类名.this.成员去访问;

匿名内部类

细节
  1. 是一个没有类名的定义在外部类的局部(如方法中)的类,同样也是一个对象;
  2. 其余细节见上述四条;
f1(new IL() {
    @override
    public void show(){
        System.out.println("当作实参传递,更加简洁高效");
    }
});
// 传统方法是创建一个类后,再创建一个对象去调用方法;

成员内部类

细节
  1. 是定义在外部类的成员位置上的类,没有static修饰;
  2. 可以添加修饰任意访问修饰符,因其类似于成员;
  3. 可以直接访问外部类的所有成员;
  4. 如果外部类和成员内部类的成员重名时,访问时默认遵循就近原则,如果想访问外部类的成员,可以使用外部类名.this.成员去访问;
  5. 外部其他类访问成员内部类的两种方式:
// First--利用外部类声明的对象去声明成员内部类
Outer outer new Outer();
Outer.Inner inner = outer.new Inner();
// Second--外部类返回成员内部类的对象
public Inner getInnerInstance(){
    return new Inner();
}

静态内部类

细节
  1. 是定义在外部类的成员位置,并且有static修饰;
  2. 可以直接访问外部类的所有静态成员;
  3. 可以添加任意访问修饰符,其类似于成员;
  4. 作用域是整个类

枚举

定义

​ 一组常量的集合

Enum Week{
    Monday("星期一"), Tuesday("星期二"), Wederday("星期三");
    private Week(String name){
        this.name = name;
    }
    private String name;
    public String getName(){
        return name;
    }
}

注解

三种基本的Annotation
  1. @Override:表明该方法是重写的父类方法;
  2. @Deprecated:表明某个程序元素已过时;
  3. @SuppressWarnings:抑制编译器警告

异常

五种运行时异常

  1. NullPointerException 空指针异常
  2. ArithmeticException 数字运算异常
  3. ArrayIndexOutBoundsException 数组下标越界异常
  4. ClassCastException 类型转换异常
  5. NumberFormatException 数字格式不正确异常

掌握异常种类,比如一种是 error,一种是 exception,知道他们的区别,以及能够举例对应的例子

异常处理

  1. 编译异常,在程序中必须使用try-catch或throws进行处理;
  2. 运行异常,如果程序不处理,那么默认是throws处理;

throw与throws的区别

  1. throws是异常处理的一种方式,位于方法声明处,后面紧跟异常类型;
  2. throw是手动生成异常对象的关键字,位于方法体中,后面紧跟异常对象;
包装类 — 八种基本数据类型相应的引用类型;
装箱
Object obj = true ? new Integer(1) : new DOuble(2.0);
// 三元运算符,须看作一个整体,因此obj的值为1.0(当前最高精度是double)
Integer缓存的数值范围是[-128,127]

String类

StringBuffer — 多线程

与String的相互转换
String str = "halo";
// First 构造器
StringBuffer stringbuffer = new StringBuffer(str);
// Second append
StringBuffer stringbuffer = new StringBuffer();
stringbuffer.append(str);

StringBuffer stringbuffer = new StringBuffer("哈喽");
// First 构造器
String str = new String(stringbuffer);
// Second toString
String str = stringbuffer.toString();

StringBulider — 单线程

线程不安全的原因

​ append方法中没有限定synchronized,致使程序可以并行操作。

String、StringBuffer、StringBuilder的区别

  1. String:不可变字符序列,效率低(做大量修改时,会导致大量副本字符串对象因丢弃而存留在内存中,影响程序性能),但复用率高(变量存放在常量池中,值相同的变量指向同一处);
  2. StringBuffer:可变字符序列,效率较高(增删),线程安全;
  3. StringBuilder:可变字符序列,效率最高,线程不安全。

Vector 和 ArrayList的比较

  1. Vector属于可变数组,线程安全,但效率不高(synchronized),其扩容倍数有两种方式:使用无参构造器创建数组时,默认容量是10,满后2倍扩容;使用有参构造器创建指定大小数组时,按2倍扩容;
  2. ArrayList属于可变数组,线程不安全,但效率高,其扩容倍数有两种方式:使用无参构造器创建数组时,默认容量为,第一次扩容到10,从第二次起1.5倍扩容;使用有参构造器创建指定大小数组时,按1.5倍扩容。

Arraylist和LinkList的比较

  1. ArrayList由于需要扩容的原因致使在增删的效率较低,但其改查的效率较高(索引定位);
  2. LinkList是双向链表,线程不安全,增删上可通过链表追加而效率较高,但其改查的效率较低(从头追查)。

HashSet

HashSet的底层维护了一个HashMap。
HashSet hashSet = new HashSet();
// 底层
public HashSet() {
    map = HashMap<>();
}
扩容机制

​ 第一次添加,扩充table容量为16,阈值(threshold)为12(16*0.75);超过阈值后2倍扩容。

Map

Map map = new HashMap();
四大遍历方式
  1. 先取出所有的Key,通过Key取出对应的Value;
Set keyset = map.keySet();
for(Object key : keyset) {
    System.out.println(key + "-" + map.get(key));
}
  1. 迭代器
Iterator iterator = keyset.iterator();
while(iterator.hasNext()) {
    Object key = iterator.next();
    System.out.println(key + "-" + map.get(key));
}
  1. 通过EntrySet来获取
Set entrySet = map.entrySet();
for (Object entry : entrySet) {
    Map.Entry m = (Map.Entry) entry;
    System.out.println(m.getKey() + "-" + m.getValue());
}
  1. 迭代器
Iterator iterator = entrySet.iterator();
while(iterator.hasNext()) {
    Object next = iterator.next();
    Map.entry m = (Map.Entry) next;
    System.out.println(m.getKey() + "-" + m.getValue());
}
public classHashMapSource2 {
    public static void main(stringl args)
        HashMaphashMap=new HashMap();
        for(inti=1;i<=12;i++){
            hashMap.put(new A(i),"hello");
        }
    }   
}
classA{
    private int num;
    public A(int num) {
        this.num = num;
    }

    @Override
    public int hashCode(){
        return 100;
    }
}

HashTable

细节
  1. 键和值不能为null,否则会抛出NullPointerException;
  2. 线程安全(synchronized),而HashMap是线程不安全的;
  3. 初始容量为11,阈值为8(11*0.75),超过阈值后2倍+1进行扩容。

应用场景

  1. 判断存储类型(一组对象(单列)或一组键值对(双列));
  2. 单列:Collection接口

​ 2.1 允许重复:List

​ 2.1.1 增删多:LinkedList(底层是双向链表);

​ 2.1.2 改查多:ArrayList(底层是Object类型的可变数组);

​ 2.2 不允许重复:Set

​ 2.2.1 无序:HashSet(底层是HashMap — 数组+链表+红黑树)

​ 2.2.2 排序:TreeSet(底层是TreeMap,将比较器传入有参构造器中,指定排序规则)

           2.2.3 插入和取出顺序一致:LinkedHashSet(底层是LinkedHashMap -- 数组+双向链表)
  1. 双列: Map

​ 3.1 键无序:HashMap(底层是哈希表 — 数组+链表+红黑树)

​ 3.2 键排序:TreeMap

​ 3.3 键插入和取出顺序一致:LinkHashMap(底层是HashMap)

​ 3.4 读取文件:Properties

泛型

List<Integer> list = new ArrayList<>();
细节
  1. 给泛型指向的数据类型必须是引用类型,不能是基本数据类型;
  2. 给泛型指定具体类型后,可以传入该类型或者其子类类型(extends);
  3. 使用泛型的数组不能被初始化;
  4. 静态方法不能使用类的泛型。(在类加载时对象尚未创建,因此JVM不能确定,不能初始化)

互斥锁

细节
  1. 同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象);
// First
public synchronized void sell(){}
// Second
public void sell(){
    synchronized(this){}
}
// Third 针对同一个对象创建的多线程
Object object = new Object();
public void sell(){
    synchronized(object);
}
  1. 同步方法(静态的)的锁为当前类本身。
class Sell implements Runnable {
    // First
    public synchronized static void m1() {}
    // Second
    public static void m2() {
        synchronized (Sell.class){}
    }
}

发表评论

后才能评论