查看原文
其他

程序汪帮公司面试3年1万8的Java程序员,基础的问题没回答好啊

我是程序汪 我是程序汪 2021-09-08



疫情期间,大家注意防护,上班带口罩下班带口罩,五一放假家里蹲



项目介绍


很多人介绍项目全链路都说不清楚,这样给面试官的影响非常差

这个面试者项目经验是银行的积分商城项目,

只少需要把积分怎么产生的或从哪里来,然后怎么对外提供查询,这之间经过多少个系统,技术亮点在什么地方,面试官一般比较关心亮点,如果你把项目说成一个简单的CURD

薪资肯定要不高了


介绍项目建议

1 业务的全链路逻辑清晰都表达出来

2 一定把技术的亮点展示出来

3 功能的设计思路,如表设计 设计模式的应用


项目亮点吧

  1. 主流技术框架必须包含的,SSM、缓存、MQ、微服务,前提你必须真用过

  2. 复杂业务,你只有简单的CRUD也没关系,面试初级程序员可以的,但是高级就不行了,只少给面试官说一个相对复杂点的场景吧

  3. 并发多线程场景,这是加分项,spring线程池怎么用啊,多线程什么场景里用啊,说的非常清楚,必须加分

  4. 第三方接口调用,如调用银行接口,里面关于异常怎么定义啊,失败机制、重试机制、幂等机制,说清楚就是加分

  5. 代码的优雅设计,项目中用了模板啊、单例、高级泛型啊、异常设计、日志啊、拦截器啊、自定义注解啊、枚举高级特性啊,都可以拿来说

  6. java8新特性,如java流式语法出来好久了,你用过能给面试官说说他的好处及常见的方法,必须加分



集合之HashMap




集合是面试最频繁的题型之一,HashMap也是我最喜欢问的



  • 返回对象的哈希代码值(就是散列码),用来支持哈希表,例如:HashMap

  • 可以提高哈希表的性能

  • 先看下Object源码的hashCode方法


hashcode:计算键的hashcode作为存储键信息的数组下标用于查找键对象的存储位置

程序汪非常喜欢问 hashCode、equals ,以前面试被虐了


通俗的解释

hashcode就类似 门牌号,小区非常大但定位你住哪里告诉门牌号就可以,非常快速定位到(非常像组数下标)

equals就是找到门牌号后需要比较里面具体的房间,



18K程序员Java中的hashcode是干嘛的,居然不知道

HashMap 为什么线程不安全?

Java 经典面试题:为什么 ConcurrentHashMap 的读操作不需要加锁?



集合中的迭代器意义




迭代器的作用

由于Java中数据容器众多,而对数据容器的操作在很多时候都具有极大的共性,于是Java采用了迭代器为各种容器提供公共的操作接口

解耦效果

使用迭代器iterator可以使对容器的遍历操作完全与其底层相隔离,可以到达极好的解耦效果

这些都是基础知识,很多人平时天天用迭代器,但是可能没注意为啥要设计这个iterator






public static void main(String[] args){ List<String> list=new ArrayList<>(); list.add("我是程序汪");        list.add("抖音");        list.add("微信"); for(Iterator<String> it=list.iterator();it.hasNext();) { System.out.println(it.next()); if(xxx){ list.remove();//翻车写法 it.remove();//正确写法            } } }


容易翻车的地方

遍历集合时删除特定元素一定要用Iterator的remove,别用集合自带的remove哦

java.util.ConcurrentModificationException


在集合内部维护一个字段modCount用于记录集合被修改的次数,每当集合内部结构发生变化(add,remove,set)时,modCount+1。

  在迭代器内部也维护一个字段expectedModCount,同样记录当前集合修改的次数,初始化为集合的modCount值。当我们在调用Iterator进行遍历操作时,如果有其他线程修改list会出现modCount!=expectedModCount的情况,就会报并发修改异常java.util.ConcurrentModificationException


结记住5个单

  • Iterator

  • remove

  • modCount

  • expectedModCount

  • ConcurrentModificationException




集合的排序




这个就是对Java集合工具熟悉的考察,当然你能说清楚下面这些更佳

java集合的工具类Collections中提供了两种排序的方法,分别是:

  1. Collections.sort(List list)

  2. Collections.sort(List list,Comparator c)


第一种称为自然排序,参与排序的对象需实现comparable接口,缺点会入侵代码

第二种叫定制排序,或自定义排序,需编写匿名内部类,先new一个Comparator接口的比较器对象,优点不用修改排序对象代码


//匿名内部类用起来比较开心Collections.sort(ordered, new Comparator<Student>() { @Override public int compare(Student t1, Student t2) { return (int) (t1.getOrder() - t2.getOrder()); } });





java8函数式排序,如果你在面试官面前也说下,印象分又飙升了

//根据学生身高排序list.sort(Comparator.comparing(Student::getHeight).reversed());



  • Comparable

  • Comparator

  • Collections.sort

  • Comparator.comparing


泛型的应用





废话不说,来个真实案例

 java中的泛型主要使用在类,方法,与接口中。首先,我们来简单的看看在类上的使用:

public class ApiResult<T> extends BaseResult { /** * 结果对象 */ private T resultObject;


//通用的结果信息定义public class BaseResult { /** * 成功标志 */ protected boolean isSuccess = true; /** * 错误信息 * */    protected String message; /** * 错误码 */    protected String errorCode; /** * 扩展信息 */ protected Map<String, String> extInfos = new HashMap<String, String>();



//程序汪对外提供的接口,微服务的哦public interface MyContentClient {
ApiResult<String> create(ApiRequest<ContentDTO> request);
ApiResult<Void> update(ApiRequest<ContentDTO> request);
ApiResult<ContentResultDTO> query(ApiRequest<ContentQueryDTO> request);}



优点: 不用每个结果对象上定义错误码等属性,设计变优雅啦

代码复用效果杠杠的



泛型类型参数作用于类上的时候主要是对多个字段及方法签名之间的类型约束。

作用于方法的时候主要是对方法的的多个参数做相应的约束,在这里方法的泛型类型参数不再举例,下面我们主要介绍类型参数的约束。


下面都有范型案例


java中泛型方法,25K的也可能没在实战项目中用过


java程序员模板设计模式真的有必要掌握下,冗余代码一扫光


Java的模板设计模式


spring的事务传播机制



7种事务的传播机制(可通过spring配置或注解来设置)

  1. REQUIRED(默认):支持使用当前事务,如果当前事务不存在,创建一个新事务。

  2. SUPPORTS:支持使用当前事务,如果当前事务不存在,则不使用事务。

  3. MANDATORY:中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。

  4. REQUIRES_NEW:创建一个新事务,如果当前事务存在,把当前事务挂起。

  5. NOT_SUPPORTED:无事务执行,如果当前事务存在,把当前事务挂起。

  6. NEVER:无事务执行,如果当前有事务则抛出Exception。

  7. NESTED:嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样。

注解配置时如:@Transactional(propagation=Propagation.REQUIRED) 

程序汪查了下公司项目代码 事务注解基本99%情况都是默认的(REQUIRED默认)


spring的注解失效翻车现场



经典案例事务注解

公司需求比较多,写代码的时候喜欢偷懒,下面是一个典型偷懒翻车现场,事务注解没生效

public class WePageManagerServiceImpl implements WePageManagerService {
@Override public void pagePublish(MysRequest request) { bizPublishHandler(request); }
@Transactional(rollbackFor = Exception.class) protected ProcResult<String> bizPublishHandler(WePagePublishRequest request) { //多表dao操作...... }}


解决方案很简单

把事务代码下沉,用一个类去单独处理


public class WePageManagerServiceImpl implements WePageManagerService {
@Autowired private BizTransaction bizTransaction;
@Override public void pagePublish(MysRequest request) { bizTransaction.pagePublishHandler(request); }}
@Service@Transactional(rollbackFor = Throwable.class)public class BizTransactionImpl implements BizTransaction{ protected ProcResult<String> pagePublishHandler(WePagePublishRequest request) { //多表dao操作...... }}


@Transactional失效原因分析:

自身调用导致失败

在应用系统调用声明@Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,再由这个代理对象来统一管理,当在Service实现类直接调用内部方法时,其本质是通过this对象来调用的方法,而不是代理对象,因为会出现事务失效的情况

总结一句话,自身调用没有经过 Spring 的代理类

事务失效3种常见原因

  • 自身调用(面试最爱问啦)

  • 异常被吃

  • 异常抛出类型


晚点程序汪会更新B站视频,欢迎大家三连


程序汪往期精彩文章包含答案





程序汪最近整理的BAT大小厂面试题2019 (面试题目录推荐)

目录:我把精华文章都整理出来了

程序员新人刚进公司很懵逼,程序汪给5个建议

程序汪推荐你去阿里巴巴java后端岗位,进来看看

疫情当下,帮公司远程技术电话面试java期望1万7千程序员

继续帮公司面试2万的java程序员,一轮电话面试很基础

程序汪粉丝2020春招java后端经验分享小米1万8、国家电网

100多个免费API接口分享 调用完全不限次数,以后总用得着

通过一个demo学会互联网API接口的使用

给个[在看],是对程序汪最大的支持
: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存