每日总结 Day 2 (不知道能坚持几天)
11.30
早上起来有点难受,去校医院发现有点发低烧,应该是宿舍交叉感染了,大伙要做好防护
Java八股文10:00-12:15
JDK、JRE、JVM
- JDK是java开发工具包,是功能齐全的JAVA SDK(软件开发工具包,能够帮助开发者快速进行开发,可以理解为Utils)里面包括了Java编译器(javac)、java调试器、JAVA核心API、JRE等开发工具,用于进行JAVA开发使用
- JRE是JAVA运行环境,提供在计算机上运行java程序所需的最小运行环境
- JVM是java虚拟机,作用是将javac编译生成的字节码文件转换为电脑能够识别的机器码,并且负责程序的执行
- Java开发⼯具包=Java 运⾏环境+Java开发⼯具
- Java 运⾏环境=Java虚拟机+Java核⼼类库
- 执行步骤
- 编写JAVA程序(.java)需要JDK
- 将编写好的.java程序编译成.class的字节码 需要JDK中的javac
- 字节码转换为机器能够识别和执行的机器码 需要JVM
- 操作系统执行机器码,则需要JRE
字节码
字节码是 Java 程序编译后的中间代码,是⼀种可移植的⼆进制代码,可以在任何⽀持 Java 虚拟机(JVM)的平台上运⾏。字节码通过将 Java 源代码编译为字节码指令序列,使得 Java 程序可以跨平台运⾏,即使是在不同的操作系统和硬件平台上也可以运⾏。
- 可移植性:Java程序通过编译形成的字节码(.java->.class),可以在任何的JVM上运行,使得程序有可移植性,这也是java跨平台的重要特征
- 安全性:由于字节码需要在JVM中运行转换,所以对字节码进行安全检查,即可确保程序不会对系统构成威胁
- 性能:字节码是一种紧凑的二进制格式,相比于直接编译为机器码,可以更快的加载和传输,同时可以在运行时进行动态优化,提高执行效率
- 可读性:相比于机器码更易读,可以进行反编译和调试
final的作用
- 对于修饰类:可以让类无法被继承,且该类的方法都是默认final关键字,所以无法对类的方法进行重写
- 对于修饰方法:表示该方法无法被子类进行重写
- 对于修饰变量:表示该变量只能被赋值一次,且不能再次修改,如果定义的时候没有进行赋值,那么只有在类的构造函数中才能初始化
- 具体作用
- 安全性:确保被final修饰的变量不会再次改变
- 可读性:将常量修饰为final可以提高可读性,因为常量的值也不会被修改
- 优化:final 变量在编译时被转换成常量,这可以提⾼程序的性能
equals、hashCode、==
- hashCode没有equals可靠,所以equals为true,hashCode一定相等,反之不能推导(有hash碰撞之类的)
- equals方法默认使用的是==操作符,所以要两个对象引用指向的是同一个对象的时候才会返回true,大部分情况下会重写对象的equals进行自定义比较
- ==操作符对于基本类型进行比较值是否相等,对于引用类型,用于比较两个对象的引用是否相等,即比较两个变量引用是否指向同一个对象。
- equals用于比较两个对象的值是否相等,对象的值⽐较往往需要根据对象的实际情况来定义,因此⼀般需要重写 equals ⽅法。如果不进行重写,那么本质上还是进行的==比较,因为每个类都继承了Object类,其中的equals方法就是进行的==比较。
- 总结:
- 如果两个对象equals相同,hashCode⼀定相同
- 如果两个对象equals不同,hashCode不⼀定不同
- 如果两个对象的hashCode相同,它们的equals并不⼀定相同
- 如果两个对象的hashCode不相同,它们的equals⼀定不相同
- 为什么要重写equals的时候要重写hashCode
- 重写equals是进行对象的内容的自定义比较,即两个内容相同的类要返回true
- 重写hashCode是为了保证内容相同的类返回相同的Hash值 Object.hash() 进行重写
- 因为在使用散列表数据结构的时候
public、private、protected、NULL
反射
Java反射(超详细!)_一个快乐的野指针~的博客-CSDN博客
力扣 13:10-14:55
1657. 确定两个字符串是否接近 中等
- 思路:对于第一个交换判断,直接把字符串变成字符数组,然后用Arrays.sort最后用Arrays.equals对数组内的元素进行比较是否相等。对于第二个判断,因为字符串中的都是小写字母,所以初始化两个new int[26]用于统计每一个字符串的具体字母的个数,然后进行一个遍历要是word1有的word2没有或者反过来,那么就返回false,然后再对数组进行排序,最后然后返回比较结果
- 注意点:第二个的判断可以抽象成为比较字母数量,也就是说一个字母的有2个,两个字母的有几个这意思,还需要额外判断两个集合所包含字母的种类是一样的。
package com.Ewan.每日一题;
/*
* @Author Ewan
* @Date 2023/11/30
* @Description:
*/
/**
* 1657. 确定两个字符串是否接近
* 提示 中等
*/
public class CloseStrings {
public boolean closeStrings(String word1, String word2) {
if (word1.length() != word2.length()) return false;
//第一种操作
char[] word1CharArray = word1.toCharArray();
char[] word2CharArray = word2.toCharArray();
Arrays.sort(word2CharArray);
Arrays.sort(word1CharArray);
if (Arrays.equals(word1CharArray, word2CharArray)) return true;
//第二种操作
int[] memo1 = new int[26];
int[] memo2 = new int[26];
for (int i = 0; i < word1CharArray.length; i++) {
int num1 = word1CharArray[i] - 'a';
memo1[num1]++;
int num2 = word2CharArray[i] - 'a';
memo2[num2]++;
}
for (int i = 0; i < memo1.length; i++)
if ((memo1[i] == 0 && memo2[i] != 0) || (memo1[i] != 0 && memo2[i] == 0)) return false;
Arrays.sort(memo1);
Arrays.sort(memo2);
return Arrays.equals(memo1, memo2);
}
}
121. 买卖股票的最佳时机 简单
- 只能买一次,因为有两个状态:持有,不持有,所以需要定义一个二维dp
package com.Ewan.动态规划.股票;
/*
* @Author Ewan
* @Date 2023/11/30
* @Description:
*/
/**
* 121. 买卖股票的最佳时机
* 简单
*/
public class MaxProfit {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][2];
//0表示不持有 1 表示持有
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i = 1; i < prices.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
//前一天持有的 或者 今天持有的 取一个最大的
//只能买卖一次!!所以取一个持有的最大值,也就是最便宜的时候买
//因为只能买卖一次 所以每次买入的时候的初始值是0 这就是和II的区别点
dp[i][1] = Math.max(dp[i - 1][1], 0 - prices[i]);
}
return dp[prices.length - 1][0];
}
}
122. 买卖股票的最佳时机 II 中等
- 这里和I的不同点就在于可以进行多次交易,所以在dp[i] [1]的递推公式上有点不一样,可以是前一天未买的状态 - 今天买入
package com.Ewan.动态规划.股票;
/*
* @Author Ewan
* @Date 2023/11/30
* @Description:
*/
/**
* 122. 买卖股票的最佳时机 II
* 中等
*/
public class MaxProfitII {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][2];
//0表示不持有 1 表示持有
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i = 1; i < prices.length; i++) {
//昨天不持有 和 昨天持有今天卖出
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
//昨天不持有今天买入 和 昨天不持有
//这样就表示可以多次买入卖出 和这个就是和I的区别点
dp[i][1] = Math.max(dp[i - 1][0] - prices[i], dp[i - 1][1]);
}
return dp[prices.length - 1][0];
}
}
123. 买卖股票的最佳时机 III 困难
- 这道题拿到就是懵的,至多交易两次?不知道如何控制这个状态
- 后面看视频才晓得,就是多定义几个状态dp[i] [5]
- 0:不进行任何操作
- 1:第一次持有的最大利润
- 2:第一次卖出的最大利润
- 3:第二次持有的最大利润
- 4:卖出的最大利润
- 这样一分,思路就一下清晰了,和前两个题还是一样的套路,由于可以多次买入,所以要和前一天的比较取一个最大值
- dp[i] [1] 这个表示的不是非要在第i天持有,也可以是之前就买了的,一直传递过来的状态
- 初始化:初始化还是有点怪,一开始做的时候我就初始化了dp[0] [1]没有意识到可以当天买然后又当天卖这个点
今天的力扣就做到这里了捏 ~ ~ ~
写报告15:10-15:20
写个要交的作业报告
设计模式15:10-17:43 19:40-21:40
设计模式
设计模式的目的
- 代码重用性(重复功能的代码,不用重新编写)
- 可读性(程序员的统一规范,让别人也能看懂你的代码)
- 可扩展性(当出现新的需求的时候能够扩展功能)
- 可靠性(新扩展的功能不会对原有功能影响)
- 使程序呈现高内聚、低耦合的特性(低耦合:功能之间的依赖性不高不会互相影响。高内聚:模块外部是高内聚的)
设计模式的七大原则
单一职责原则
- 概念:对类来说,每个类只负责某一个职责。如果A类即负责A1这个职责又负责A2这个职责,那么当职责1需求变动的时候可能会影响到A2,所以这里要细分职责,分为A1和A2两个类,遵循单依职责原则。
- 注意事项:
- 降低类的复杂度,每个类只负责一个职责
- 提高类的可读性和课维护性
- 降低变更带来的风险(每个类只负责一个职责所以在修改的时候不会影响到其他的类)
- 通常情况下应当遵守单一职责原则,只有在某些情况逻辑足够简单,才能在代码层面违反单一职责原则;只要类中的方法足够少,那么可以在类方法中实行单一职责原则
接口隔离原则
- 概念:客户端不应该依赖他不需要的接口,即一个类对另一个类的依赖(使用)应该建立在最小的接口上
- 即一个类对接口的使用时,只会用到这个接口的几个方法,那么这时候就把这个接口拆分
- 场景引入
依赖倒转原则
- 概念
- 高层模块不应该依赖低层模块,二者都应该依赖其抽象
- 抽象不应该依赖细节,细节应该依赖抽象
- 依赖倒转(倒置)的中心思想是面向接口编程
- 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架 构比以细节为基础的架构要稳定的多。在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类
- 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成
- 依赖关系的三种传递方式
- 接口传递
- 构造函数传递
- setter传递
- 情景1:传统的模式,人要接受QQ调用QQ的发送信息功能。这种设计扩展性不高,需要改动的多,如果现在要用WX来发送消息,这种模式就得创建一个WX的类,然后又需要在Person类中重新定义一个方法
static class QQ {
public void getInfo() {
System.out.println("this message is from qq");
}
}
static class Person {
public void receive(QQ qq) {
qq.getInfo();
}
}
public static void main(String[] args) {
Person person = new Person();
person.receive(new QQ());
}
- 解决方法:引入一个抽象的接口 IReceiver, 表示接收者, 这样 Person 类与接口 IReceiver 发生依赖
static interface IReceiver {
void getInfo();
}
static class QQ implements IReceiver {
@Override
public void getInfo() {
System.out.println("this message is from qq");
}
}
static class WX implements IReceiver {
@Override
public void getInfo() {
System.out.println("this message is from WX");
}
}
static class Person {
public void receive(IReceiver receiver) {
receiver.getInfo();
}
}
public static void main(String[] args) {
Person person = new Person();
person.receive(new QQ());
person.receive(new WX());
}
- 从这个情景中可见在拓展WX这个业务的时候,并没有多原有的代码进行更改,而是直接写了一个WX的类去实现IReceiver
- IReceiver这个接收器就是抽象出来的,他并不管你用什么东西来发送,不管你是如何实现细节的
- 即抽象(IReceiver)不依赖细节(QQ、WX),细节(QQ、WX)依赖抽象(IReceiver)
- 注意事项
- 层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好
- 变量的声明类型尽量是抽象类或接口, 这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展 和优化
- 继承时遵循里氏替换原则
总结
今天还是学到挺多东西的,发现自己很多比较基础的东西都忘记了,是要得好好补一补
本来是打算寒假试试找实习了,仔细想了想,我感觉目前还是得以学技术为主要的(而且大家都说寒假实习挺少机会的),很多东西都不了解比如并发编程、JVM、Netty、设计模式这种,然后就是很多东西学过的都忘记了比如Spring的AOP、反射这类的知识,当时学就没有太过于认真,导致遗忘的挺多的,以后学习新知识还是得做做笔记,一来可以巩固记忆,二来可以打起精神(纯看视频的话是真的很不容易吸收)
明日计划
- 继续做股票的动态规划部分
- 设计模式剩余四个原则的学习
- 锻炼(今天有点烧没去,明天一定去!)
好了今天就这样了 睡觉了
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
Day 1✅ 今天做了:完成AI应用速通教程第一章、第二章、第三章前半节学习⏰ 明天计划:完成第三章后半节、第四章学习📚 今日感悟:理解机器学习、深度学习基础、transformer架构等
1
Day 12✅ 今天做了:AI 知识库面试通关120问(60-80);RAG知识库项目(知识库问答);MySQL 八股背诵;回溯算法题。⏰ 明天计划:AI 知识库面试通关120问(40-60);RAG知识库项目(Query优化);算法题。📚 今日感悟:验证RAG 知识库问答功能时,由于后端日志过于简略,人工排查难以定位问题所在,在借助 Claude Code后,仅提供项目目录与问题描述,AI 扫
2
day2(8.1)今日学习了rag的进阶知识,练习口诉了rag的流程。
1
独立开发一个企业级Web系统:斗篷系统(ABcloakPro)的开发实践
2
编程导航什么时候出个深色皮肤背景或者阅读模式呢,这么白长时间看真的废眼
1
