![](https://img-blog.csdnimg.cn/20201014180756754.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
java基础进阶
文章平均质量分 92
smart哥
一名有10余年经验的互联网老兵,历经从传统软件公司到大型互联网公司的洗礼,早年在中兴通讯等大型通信公司担任项目leader,后随着互联网的崛起,先后在前美团支付等大型互联网公司担任架构师。对互联网架构底层技术有相当的研究和独特的见解,在多个领域有着丰富的实战经验。
展开
-
巧用函数式接口
/ 写了一个方法,参数是函数式接口。对于函数式接口,一般可以传递3类参数:实现类对象、Lambda、方法引用try {// 接下来演示分别传递3类参数。3~7演示的是方法引用。// 1.传入匿名对象@OverrideSystem.out.println("匿名对象");});// 2.使用Lambda,()表示Runnable#run()的参数,println()是Runnable#run()的方法体。原创 2023-12-01 09:14:27 · 893 阅读 · 0 评论 -
Java8 Optional
我的体会是,Optional并不难,就是一个工具类,没几行代码,并且不存在丝毫的继承关系。难的是很多人不知道什么时候该用Optional、怎么用Optional。如果大家去百度或知乎搜索“Optional”,会发现许多文章写得并不好,它们举的例子非常空洞,我甚至觉得作者其实根本没用过Optional,就是为了介绍每一个方法而强行弄出一个例子,最终我们虽然看完了整篇文章,却无法灵活应用Optional。还是要靠大家自己实际开发时多体会体会。原创 2023-12-01 09:11:38 · 916 阅读 · 0 评论 -
Stream API练习题
考虑到Stream API在实际开发中使用的频率越来越高,而且在可读性、简洁性和实用性上都十分出色,特别新增一个练习章节,以便帮助大家更好地掌握它。原创 2023-11-30 08:29:25 · 1053 阅读 · 0 评论 -
Java8 Stream API
所以JDK的做法是,把获取Stream的一部分方法封装到StreamSupport类,另一部分封装到Stream类,StreamSupport用来补足原先的集合体系,比如Collection,然后引入default方法包装一下,内部调用StreamSupport完成偷天换日。比如filter后面还可以跟map等操作,那么filter就是中间操作,而collect后返回的就是元素了,而不是流,无法继续使用。就好比一缕山泉,经过小草、小花、竹林,还是一缕水,但到了你的锅里煮成一碗粥,就没法继续使用了。原创 2023-11-30 08:20:50 · 875 阅读 · 0 评论 -
分享几种 Java8 中通过 Stream 对列表进行去重的方法
提供的方法,返回的是由该流中不同元素组成的流,方法来判断重复元素,因此,我们可以通过重写。,原理就是判断一个元素能否加入到。方法来达到某些特殊需求的去重。方法,所以可以去重成功。我们首先创建一个方法作为。的参数,其返回类型为。注:代码中我们使用了。原创 2023-11-30 08:12:37 · 3441 阅读 · 0 评论 -
函数式接口
我们可以理解为Java8支持传递方法(之前只能传递基本数据类型和引用类型),也可以按原来面向对象的思维将Lambda理解为“特殊的匿名对象”。原创 2023-11-29 07:56:05 · 1130 阅读 · 1 评论 -
Lambda表达式与方法引用
所谓的方法引用,就是把方法搬过来使用。,说明Lambda逻辑已经变了,此时原先的方法引用就不匹配了,不能再用了。你最多只能调用Teacher::getAge(),但是这个方法引用的逻辑是“获取老师的年龄”,而不是“首先,filter()的参数要么是Lambda表达式,要么是方法引用,不能是方法引用+语句,不伦不类。兄弟,如果已经存在某个方法能完成你的需求,那么你连Lambda表达式都别写了,直接引用这个方法吧。,然后把那个方法引用过来,而不是想着改变原来的MyInteger::Compare,原创 2023-11-29 07:49:25 · 1144 阅读 · 0 评论 -
接口多态与方法多态
在上一篇设计山寨版Stream API时,有一个技巧被频繁使用:接口多态。接口,用的是函数式接口,即接口内部有且仅有一个抽象方法。多态,原本指的是接口下有多个子类实例可以指向接口引用,但由于函数式接口恰好仅有一个方法,此时接口多态等同于“方法多态”,即一个抽象方法拥有多个不同的具体实现。原创 2023-11-29 07:45:07 · 966 阅读 · 0 评论 -
山寨Stream API设计分析
其中,Lambda表达式最“难”。它的“难”在于抽象,初学者根本不知道为什么要这么写、写了又如何起作用。好在《Lambda表达式》已经解答了这个问题。世界上有两种答案,真理or你期望的答案。个人觉得,对于Lambda表达式和Stream API,我们只要得到期望的答案即可。Lambda表达式底层到底是不是匿名内部类呢?其实不是。但这不妨碍我们认为Lambda表达式是“掐头去尾”的匿名内部类,然后顺手再把Stream API学了,马上应用到实战中。这,才是最重要的。原创 2023-11-28 09:07:54 · 1246 阅读 · 0 评论 -
山寨Stream API
MyList虽然很像Stream API,但本质还是对List进行外部迭代,而正版的Stream API是先产生Stream流,再通过流迭代,属于内部迭代。本文只是借助这个例子切入Stream API的学习,你们也不可能在实际项目中放着正版Stream API不用,而拷贝我的山寨版。我写了一个山寨版的Stream API,实现了其中的filter()和map(),底层原理稍有不同,仅做知识引入。乍一看很麻烦,好像还不如直接写各种for,但我是为了复用,所以抽取了MyList类。看不懂没关系,感受一下即可。原创 2023-11-28 08:12:11 · 478 阅读 · 0 评论 -
Lambda表达式
尽管使用了策略模式,上面的代码还是有问题。当然,我们还可以从另一个角度理解:Java8的Lambda都是基于上下文推导的,当一个接口只有一个方法时,推导结果是唯一确定的,但是方法不唯一时,无法推导得到唯一结果。什么是方法引用,我们后面再介绍,可以单纯地理解为可复用的Lambda(把其他类已经定义的方法作为Lambda),实际开发时依靠IDEA提示改进即可,并不需要我们记忆。嗯,没错,到此为止这大概是JDK8之前我们能想到的最好的解决办法,不仅运用了策略模式,还使用匿名类的方式成功阻止了类的暴增。原创 2023-11-28 08:08:39 · 941 阅读 · 0 评论 -
数组与链表
理应来说LinkedList作为链表结构,插入删除操作应该比ArrayList效率高,但在遍历的大前提下,LinkedList只要涉及索引操作(index),由于get(i)/set(i, e)等方法内部需要遍历,最终表现往往不如ArrayList。最后的结论就是,除非你要用list进行头插入或头删除,否则都是ArrayList快。但你觉得这种情况多吗?是什么需求这么变态呀?所以我在构建山寨Stream API时没有考虑LinkedList,也推荐大家平时不知道用哪种List时,优先选择ArrayList。原创 2023-11-27 08:26:17 · 931 阅读 · 0 评论 -
如何处理枚举类型(下)
*** 自定义枚举转换器(直接抄StringToEnumConverterFactory)*/@Override/*** StringToEnumConverterFactory默认是调用Enum.valueOf(),也就是根据Enum.name匹配* 我们改成根据Enum.ordinal匹配* @return*/@Override@Override// 把我们自定义的枚举转换器添加到Spring容器,Spring容器会把它加入到SpringMVC的拦截链路中。原创 2023-11-27 08:05:08 · 1182 阅读 · 0 评论 -
如何处理枚举类型(上)
在正式改代码之前,我们先来解决一个疑惑:JdbcType是什么?不论是EnumTypeHandler还是EnumOrdinalTypeHandler,setNonNullParameter()的参数列表都有JdbcType:而且EnumTypeHandler的setNonNullParameter()内部还对JdbcTye做了判断。所以,什么是JdbcType呢?原创 2023-11-25 16:26:29 · 1029 阅读 · 0 评论 -
枚举与应用
枚举是一种特殊的类,和class、interface等是一个级别的(其实就是一个类),一般用于表示多种固定的状态。《阿里巴巴开发手册》对枚举的介绍:我们在设计山寨枚举中用WeekDay表示周一到周日,但正版枚举的格式要精简很多:注意,WeekDayEnum命名规则并不是固定的,但推荐以Enum结尾,方便见名知意。当一个类声明为enum时,表示这是一个枚举类,比如enum WeekDayEnum。原创 2023-11-25 14:28:53 · 934 阅读 · 0 评论 -
设计山寨枚举
但实际上,常量类仅仅是解决了第一个问题:业务含义明确,代码可读性提高。但调用者仍然可以随意传参,比如仍然允许传入-1。如果希望对入参进行限制,可以对POJO的set方法进行约束:然而抛异常并不是最优解,虽然确实最终阻止了错误发生,但是太迟了!调用者在编写代码时仍然可能在毫不知情的情况下写出setRestDay(-1)这样的语句(IDEA只会提示传入Integer类型,却不会提示范围是1~7)。原创 2023-11-24 07:55:54 · 782 阅读 · 0 评论 -
从设计上理解JDK动态代理
照理说,动态代理经过前面3篇介绍,该讲的都已经讲完了,再深入下去的意义不是特别大。但看到群里有小伙伴说对InvocationHandler#invoke()方法的参数有些困惑,所以又补了一篇。上一篇也是这么介绍的,但大家的接受度似乎不是很好,甚至对参数怎么传进来的感到困惑,所以本篇打算站在Proxy类设计的角度分析三个参数的由来。当然啦,我还远不敢说能写出JDK级别的代码。本文虽然也尝试编写MyProxy类,但它是用来解释参数由来的,意义并不在于完美复刻JDK Proxy。原创 2023-11-24 07:44:46 · 945 阅读 · 0 评论 -
浅谈JDK动态代理(下)
上一篇我们已经顺利通过接口得到代理Class对象,有了代理Class对象意味着代理对象唾手可得。原创 2023-11-24 07:40:20 · 1002 阅读 · 0 评论 -
浅谈JDK动态代理(中)
Class类只有一个,却要描述形形色色的各种类,比如Person类、Student类,那么如何区分谁是谁的Class对象呢?也就是说,接口Class的对象和实现类的Class对象除了构造器,其他信息基本相似(目标类由于继承了Object,所以内部包含了Object的方法,与代理无关)。类是用来描述一类事物的,我们有Person类描述“人”,Student类描述“学生”,而Class类就是用来描述“类”的。理论上只要编写了类,那么通过JVM通常可以得到该类的对象,Class类的对象就是Class对象。原创 2023-11-23 07:50:46 · 140 阅读 · 0 评论 -
浅谈JDK动态代理(上)
到目前为止,在Java基础进阶这个章节,我们已经帮大家梳理了很多晦涩但极其重要的知识点,包括反射、注解和泛型。这些都是我们迈向中高级程序员的小碎步,我们已经离“成熟的码农”越来越近了,但还不够。今天,我们仍需一起再往前走一小步:JDK动态代理。个人认为Java基础有“四大神兽”,除了刚才说的反射、注解和泛型,JDK动态代理就是最后一道坎。“动态代理”四个字一出来,估计很多初学者已经开始冒冷汗。尽管动态代理看起来似乎有一定难度,但却必须拿下。原创 2023-11-23 07:43:26 · 133 阅读 · 0 评论 -
泛型类与泛型方法
泛型类上的其实是一种“声明”,如果把类型参数T也看做一种特殊的变量,那么就是变量声明(不是我们一般概念中的变量声明,一个作用于运行期,一个作用于编译期)。由于泛型类上已经声明了T,所以类中的字段、方法都可以自由使用T。但是当T被“赋值”为某种类型后,就会在编译器的帮助下形成一种强制类型约束,此时这个通用的代码模板也就不再通用了。原创 2023-11-23 07:38:51 · 54 阅读 · 0 评论 -
泛型边界的问题
泛型只是程序员和的约定。我们可以通过泛型告诉编译器自己的呐,我现在假定这个List只能存String,你帮我盯着点,后面如果不小心放错类型,在提醒我。就好比Spring明明告诉你默认读取resources/application.yml,你非要把配置文件命名为resources/config.yml当然就报错啦。而泛型也有一套自己的规则,我们必须遵守这些规则才能让编译器按我们的意愿做出约束。这些规则是谁定的呢?当然是JDK的那群秃子咯。今天我们来学习泛型通配符。原创 2023-11-22 08:03:38 · 744 阅读 · 0 评论 -
泛型概述(下):泛型实现机制
上篇提到泛型可以看做是对变量类型的抽取,。但是,敏感的读者马上就会发现这tm是个悖论啊:对象类型不确定,JVM怎么创建对象啊!要回答这个问题,我们必须了解Java的两个阶段:编译期、运行期。也就是说,Java有两台很重要的机器,编译器和虚拟机。我们确实引入了泛型对所以add(1)会编译报错。我们必须去了解泛型的底层机制。原创 2023-11-22 07:54:21 · 423 阅读 · 0 评论 -
泛型概述(上):特定与泛化
把变量类型抽取成类型参数T构造出模板代码,再通过实际类型参数赋值(比如ArrayList变成ArrayList),把类型特定化,最后配合编译器在编译期对相关操作的变量类型进行约束,这就是泛型。“模板代码”其实并不是一种时髦技术,很多语言都有自己的“模板代码”,比如C++也有“泛型”,不过人家叫模板类。使用泛型时,比如ArrayList,T被替换为String,可以看做是对T的“赋值”,这里的String称为。但泛型数组其实是非常特殊的,Java并不能直接实现泛型数组。原创 2023-11-22 07:47:01 · 41 阅读 · 0 评论 -
注解案例:山寨Junit与山寨JPA
上篇讲了什么是注解,以及注解的简单使用,这篇我们一起用注解+反射模拟几个框架,探讨其中的运行原理。原创 2023-11-21 08:02:56 · 984 阅读 · 0 评论 -
再谈谈注解
public @interface 注解名称{属性列表;格式有点奇怪,我们稍后再研究。原创 2023-11-21 07:48:28 · 141 阅读 · 0 评论 -
我理解的反射
我之前对反射的理解未必精确却代表了自己当时所能理解的限度...每写完一篇文章,我都能感受到原本一个个孤立的知识由点到线,由线到面,最终拔地而起变成一个个立体的概念,让我有机会站在更高的地方去环视周围这个广袤无垠的程序世界。这感觉,会上瘾。由于反射本身确实抽象(说是Java中最抽象的概念也不为过),所以我当初写作时也用了大量的比喻。但是比喻有时会让答案偏离得更远。前阵子看了些讲设计模式的文章,把比喻都用坏了。有时理解比喻,竟然要比理解设计模式本身还费劲...那就南辕北辙了。原创 2023-11-20 11:03:26 · 362 阅读 · 0 评论 -
再谈super、static、final
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬。原创 2023-11-20 10:48:05 · 164 阅读 · 0 评论 -
浅谈面向对象
从某个角度说,你是对的,多态最大的作用就是为了传参提供便利,但我们不应该只看到这一层,还要往下再走走:为什么要用父类引用指向子类实例呢?就好比你看到一把刀很锋利,可以切菜,你不应该疑惑“难道刀就是拿来切菜的吗”,而应该关注“为什么刀可以如此锋利”...原创 2023-11-20 10:33:14 · 187 阅读 · 0 评论 -
对象与this
最近想再聊聊Java的对象与this关键字。原创 2023-11-19 09:21:54 · 93 阅读 · 0 评论 -
实用小算法
开头提醒:打开自己本地任意一个SpringBoot项目,复制代码到test包下跟着敲。后面几篇文章不再提醒,希望大家养成习惯。看10篇文章,不如自己动手做一次。我们不执着于一天看多少篇,但求把每一篇都搞懂,慢就是快。给大家分享一个非常、非常、非常实用的小算法。严格意义上,它不是一个算法,而是一种编码技巧。但其中涉及的思想层面的东西是共通的,如果能熟练掌握它,在某些场景下将大幅提升我们程序的执行效率。这个算法能解决什么问题呢?它主要处理两个数据集合的要求对数据进行处理,最终输出:梁山伯爱祝英台。原创 2023-11-19 08:49:20 · 110 阅读 · 0 评论 -
初级程序员如何进阶
我不知道其他专栏是出于什么目的,可能是公众号引流或软文推广什么的,而我写博客目的很纯粹,就是觉得自己当时被欺负了,现在懂了于是拿出来,让后面的人别再被欺负了。就好比我现在要推导一个新的数学公式,当我得证的条件最终只差证明另一个公式,而这个公式已经是公认定理时,这个新的公式就算推导成功了。这些都无法掌握,整天满口高并发、轮询、微服务...如果让我来面试,我不会问这些高大上的问题,只会和你聊基础,看你有没有自己的见解。当前不懂的知识点,是由另一个你不了解的知识点实现的...无限递归,最终你觉得自己什么都不懂。原创 2023-11-19 08:35:24 · 190 阅读 · 0 评论