跳到主要内容45 岁程序员求职困境:技术精湛为何难获面试机会 | 极客日志Java大前端java算法
45 岁程序员求职困境:技术精湛为何难获面试机会
本文探讨 45 岁程序员求职难的深层原因,分析市场供需关系、企业需求及国家层面的解决思路。文章指出年龄歧视背后是供大于求的结构性问题,建议政府引导就业平衡并提供再就业支持。同时整理了 Android 开发相关的常见面试题,涵盖基础原理、性能优化、框架源码及大厂面经,为开发者提供复习参考。
11 月 1 日,有网民留言称,"我是一名软件开发人员,今年 45 岁,精通各种技术体系……而我辞职回家半年后再回来寻找工作机会的时候,却发现连个面试机会都很难得到。"
年龄歧视和限制确实是一个很严重,也很复杂的社会问题,值得重视。以下从多个维度分析这一现象及解决思路。
从市场的机制来看
这是一个自由竞争的市场,企业倾向于招聘性价比高的人才。就像消费者在市场上购买产品一样,倾向于选择价格合适且性能满足需求的选项。
从个人的角度来看
既然年龄大了,技术也能这么牛,为什么还竞争不过年轻人?体力、精力不如年轻人是客观事实,但按正常发展逻辑,工作 10 年的人应该比工作 3 年的人技术更好。如果你的技术是企业的必需品,企业肯定不敢辞退你,反而可能是抢手货。
但是,现实却是,工作 10 年的职场人,可能技术就跟工作 3 年的水平差不多,这时候,就没有优势了。
从企业的需求来看
为什么很多企业需要技术不怎么样的年轻人,不需要技术牛逼的中年人?原因很简单:现在企业应用的技术,都很基础,并不需要那么高深的技术。
企业做的业务就是普普通通的技术就能做到,即使做到了很精通、很专深,在大部分企业尤其是中小型企业当中,是没用武之地的。在企业的角度来讲,你的技术是多余的,可称之为:剩余技术劳动力,叫:技术节余。
我花高薪聘请剩余技术劳动力,是干这点活,聘请年轻人也是干这点活,价格又不一样,企业肯定是怎么划算怎么来。
换句话来讲,我国的很多 IT 技术企业普遍的技术深度不够,或者说是企业的基础研究创新不够,用不到那么多高深技术的人才。国内到现在没几个微软、IBM、甲骨文、SAP 这样级别的公司,同类型差距太大。
这就会导致大部分公司用不到那些有技术积累的,经验丰富的中年人,所以,这就导致中年人跟年轻人相比唯一的经验和技术都没有优势了,毕竟年轻人那点技术就够用了。
再回到市场供给层面来谈一谈
大家都说企业不要 35 岁以上的人,那么为什么这么多企业还能好好活着呢?那就说明这个市场的年轻人就满足了企业的需求了。
如果整个社会一共有 100 家公司,需求是 1000 人,市场提供了 1 万人,包含 6000 年轻人,4000 超过 35 岁的中年人,那这 100 家公司肯定都会去找年轻人,因为年轻人满足了他们的需求,没有技术大佬并不影响公司的生存。
如果你是企业负责人,你会怎么选?供大于求的时候,企业就有选择权,当然选择便宜又有精力的年轻人。
从国家层面来看,该如何解决?
解决这个问题,最本质的背后是:要从国家层面出发,政府要引导正确的就业供需,保证和调节供需平衡,而不是什么行业火,就全都往这一个行业里钻,这势必就会供大于求,将选择权由企业主导。
另外一个层面就是:当供需关系失衡的时候,国家应该有一种托底的机制,就是可以引导大家通过现在的技术进行一些创新或者培训再就业,引导多余的劳动力积极探索企业就业方向,国家应该有更多的政策支持和优惠 35 岁以上的人再就业和创业,给中年人更多的,更好的就业环境。
现在很多传统企业没有自己的研发人员,很多项目都找外包公司,买模板,做系统,干的非常烂,就是因为这些企业当中没有人懂技术。
外包技术公司的盛行,也导致了程序员行业劣币驱逐良币。市场上有太多垃圾的外包公司了,既坑害程序员,又坑害那些想转型的传统企业。
从程序员自身层面,应该想办法提升自己的多维竞争力
程序员不要仅仅只关注技术,也应该关注行业的变化,趋势,要熟悉公司的各项业务,拓展的眼界,这既有助于你进入管理层,也有助你与转型或者转行。
这个问题是全社会的问题,就像是经济的发展需要自由经济这只看不见的手,也需要政府这只看不见的手一样,在就业市场上,也是这样,自由竞争保持活力,供需调节保证人才被充分利用。
目前国内环境跟国外不一样,感觉最大的问题,是我们国家人口多,劳动力多,竞争压力大,国外人少,竞争少,本质上是由供求关系导致这种现象。
Android 程序员大厂面试题整理
以下为常见的 Android 开发及相关技术面试题,涵盖基础、原理、优化及大厂面经。
常规面试题
- ListView 如何缓存的?
- RecyclerView 联系人列表如何实现 A-Z 快速定位
- 广播和 EventBus 的区别
- 主线程 Looper 循环为什么没有卡主线程?nativePollOnce
- SharedPreference 的线程安全、进程安全,如何跨进程
- Android 中实现多线程:threads, Handler, AsyncTask, IntentService
- Android 中如何实现多进程
- 自定义 View 的过程:measure,layout,draw
- LayoutInflater#inflate 的 attachToParent true 是什么意思
- theme 和 style 有什么区别,优先级
- 有哪些进程间通信方式
- View 的渲染过程
- Binder 的原理和优势
- AIDL 中的 oneway 有什么用,方向标签 in、out、inout 是什么意思
- Android 中有哪些动画,都说下
- Serializable 和 Parcelable 的区别
- 你知道哪些 Layout,ConstraintLayout 的特点是什么
- 手机开发者选项有哪些,不保留活动是什么
- 基本的数据类型有哪些?
- String、StringBuilder、StringBuffer 的区别?
- Fragment 是什么,使用场景和生命周期
- 说一下 Context 和内存泄露
- 线程创建的方法?
- Activity 的启动模式和适用场景?
- ViewPager 用过吗?然后扯到了它和 Fragment 联合;
内存泄露和内存溢出
(1)内存泄漏 (memory leak):是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
(2)内存溢出 (out of memory):指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储 int 类型数据的存储空间,但是你却存储 long 类型的数据,那么结果就是内存不够用,此时就会报错 OOM,即所谓的内存溢出。
(1)内存溢出原因:
① 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
② 集合类中有对对象的引用,使用完后未清空,使得 JVM 不能回收;
③ 代码中存在死循环或循环产生过多重复的对象实体;
④ 使用的第三方软件中的 BUG;
⑤ 启动参数内存值设定的过小
(2)内存溢出的解决方案:
① 第一步,修改 JVM 启动参数,直接增加内存。(-Xms,-Xmx 参数一定不要忘记加。)
② 第二步,检查错误日志,查看'OutOfMemory'错误前是否有其它异常或错误。
③ 第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。
四大组件
- 当内存不足时 Service 被杀死了,如何重启这个 Service
- Android 系统杀进程时,是怎么考虑进程优先级的?
- Fragment 的 ViewModel 如何访问到 Activity 的 ViewModel 的数据
- Activity 4 种启动模式说下,各种启动模式适合的应用场景
- Activity 任务栈从底到顶为 A-B-C,低内存杀死进程后,重新点击,显示哪个?这时如果 C 里面有 Fragment 是怎样恢复的?
- Activity 如何传参给 Fragment?为什么用 setArgument 传参,而不是使用带有参数的构造器?
- window、view 和 Activity 的关系
- Activity、Fragment 的各个生命周期依次说一下,各个生命周期里面适合做什么
- Activity 调用 finish 方法后怎么走到 onDestroy 的
图片
- Glide 缓存特点
- Glide 为我们做了哪些内存优化
- Glide 如何加载 GIF
- ListView 图片错位的原因,解决方案
- bitmap 如何处理大图,30M 的大图如何防止 OOM?
网络
- OKHttp 如何实现缓存
- OKHttp 的超时时间,有考虑 DNS 超时码
- OKHttp 线程池、连接池讲下
- OKHttp 的所有拦截器有哪些,请求失败了重试 1、2 次怎么做
- Retrofit 实现机制
- Room 注解如何在编译时生成类文件
- http 和 https 的区别,shakehand 的过程说下
- 状态码 400、401,3xx 有哪些
- 网络劫持是什么,应该怎么做
- TCP 三次握手,握手中的网络包各个标记位是多少,四次挥手说一下
- TCP 发送窗口是什么?
- 混合开发 h5 了解多少
- 浏览器窗口访问一个网址的过程
- POST 和 GET 有什么区别
优化
- 内存泄漏分析,LeakCanary 的原理,泄漏对象是如何找到引用链的
- APK 瘦身
- 启动优化
- 卡顿分析!!
- ANR 分析!!
- 为什么布局文件中层级越多,性能可能差很多
- 你有哪些应用性能优化的经验必问
- ProGuard 怎么写
Java
- Java 中==和 equals 和 hashCode 的区别
- int 与 integer 的区别
- 谈谈对 java 多态的理解
- String、StringBuffer、StringBuilder 区别
- 抽象类和接口区别
- Serializable 和 Parcelable 的区别
- string 转换成 integer 的方式及原理
- 哪些情况下的对象会被垃圾回收机制处理掉?
- 什么是强引用、软引用、弱引用以及虚引用?
- 什么是依赖注入?能说几个依赖注入的库么?
- 静态代理和动态代理的区别,什么场景使用?
- Java 的异常体系
- JVM 的回收算法是怎样的
- 说一下泛型原理,并举例说明
- 能说说 HashMap 常用操作的底层实现原理吗?
- 垃圾回收机制和调用 System.gc() 的区别?
- 说一下你所了解的设计模式有哪些
- 说下 java 中的线程创建方式,线程池的工作原理。
Kotlin
- Kotlin 协程为什么能以同步代码写出异步逻辑?
- suspend 函数的工作原理
- 在协程上定义了一个局部变量,为什么在其中的其他线程里的协程也能访问到?
- by 的两种场景,by Lazy 的实现
- object 单例的实现
算法
- 各种排序算法(冒泡、选择、快排、归并。。。)的时间复杂度,各种查找算法(顺序查找,二分查找。。。)的时间复杂度
- LRU 实现(146)参考 LinkedHashMap 实现的 3 个方法
- LFU 缓存 (460) 同一频率使用 LRU 的 NodeList,外面套一层 {freq to NodeList},NodeList 用双链表实现
- 两数相加(445)
- 找缺失的数字(268)注意相似题目里有中等
- 两个队列实现栈(225)
- 删除子文件夹(1233)
- 螺旋矩阵打印(54)
- 用生成随机数 1-5(1,2,3,4,5)的方法,得到一个可以生成随机数(1-7)的方法
- 54 张扑克牌,分成 3 堆,大小王出现在同一堆的概率(排列组合算数题)
Android 第三方库源码
- 网络底层框架:OkHttp 实现原理
- OKhttp 针对网络层有哪些优化?
- 网络请求缓存处理,okhttp 如何处理网络缓存的?
- 从网络加载一个 10M 的图片,说下注意事项?
- 网络封装框架:Retrofit 实现原理
- 响应式编程框架:RxJava 实现原理
- 图片加载框架:Glide 实现原理
- Glide 如何确定图片加载完毕?
- Glide 内存缓存如何控制大小?
- 加载 bitmap 过程(怎样保证不产生内存溢出)
- Android 中软引用与弱引用的应用场景。
- LruCache 原理
- Fresco 与 Glide 的对比:
- Bitmap 如何处理大图,如一张 30M 的大图,如何预防 OOM?
- 事件总线框架 EventBus 实现原理
- 内存泄漏检测框架:LeakCanary 实现原理
- leakCannary 中如何判断一个对象是否被回收?
- 依赖注入框架:ButterKnife 实现原理
- 依赖全局管理框架:Dagger2 实现原理
- 数据库框架:GreenDao 实现原理
性能优化
这个主要结合你所做过的项目问,一般面试官会问你项目做过哪些方面的优化,常见的问法就是:
- 优化的思路是什么
- 用到了哪些技术
- 遇到了哪些困难(问题)
- 如何解决
- 有什么心得
主要结合自己项目回答。切记不要自己给自己挖坑,比如没有做过这方面优化,你为了表现自己,说做过,结果面试官往下问回答不出来,这关乎诚信问题。
抽象问题
- 讲讲做过的项目,有哪些亮点
- 你自己的亮点在哪里,你的加入可以给团队带来什么
- 技术规划,怎么发展
设计题
- 如果让你设计一个音乐播放器,要实现哪些接口
- 设计一个图片下载库:深挖 Glide,如果图片没有设置有效期,如何保证缓存被更新?
部分公司真实面试题统计
(一)泰科电子面经 高级安卓工程师社招面试题目
- ContentProvider 的权限管理 (解答:读写分离,权限控制 - 精确到表级,URL 控制)
- 如何通过广播拦截和 abort 一条短信?
- 广播是否可以请求网络?
- 广播引起 anr 的时间限制是多少?
- 计算一个 view 的嵌套层级
- Activity 栈
- Android 线程有没有上限?
- 线程池有没有上限?
- ListView 重用的是什么?
- Android 为什么引入 Parcelable?
- 有没有尝试简化 Parcelable 的使用?
- 四大组件以及使用方式
- 网络请求
- get/post 请求的区别
- xml/json 的区别以及解析方式
- 谈谈对 Handler 的理解
- service 的启动方式
- 屏幕适配
- ArrayList 与 LinkedList 区别
- Application 和 Activity 的 Context 对象的区别
- Android 属性动画特性
- 如何导入外部数据库?
- LinearLayout、RelativeLayout、FrameLayout 的特性及对比,并介绍使用场景。
- 谈谈对接口与回调的理解
- 回调的原理
- 写一个回调 demo
- 介绍下 SurfView
- RecycleView 的使用
- 动态权限适配方案,权限组的概念
- Android 系统为什么会设计 ContentProvider?
- 下拉状态栏是不是影响 activity 的生命周期
- 说说 ContentProvider、ContentResolver、ContentObserver 之间的关系
- 请描述一下广播 BroadcastReceiver 的理解
- 广播的分类
- 序列化的作用,以及 Android 两种序列化的区别
- Android 中 PID 和 UID 的区别
- Binder 的理解,以及为什么要用 Binder,进程间通信的方式
- 框架搭建选型的注意点
- 第三方 SDK 应用
- MVC、MVP 设计模式
- TCP 与 UDP 的区别
- Dalvik 虚拟机方面
- EventBus 实现原理
- 对自定义 view 的理解
- 详细介绍下自己做过的项目对你的成长最大?哪个的收获最大?
- 你认为一名安卓工程师最重要的特质是什么?你在工作中最终重视的因素是什么?你在工作中是怎么保持持续学习的?
(二)咻电科技 安卓工程师 社招 面试技术题目
- mvc 和 mvp 的使用场景和优缺点
- Hashmap 实现原理
- 性能优化(一定要具体说出很多方案,比如内存、电量、流量等具体解决方案)
- 单例模式的写法和各种写法的优缺点
- okHttp、volley、retrofit 等网络框架的使用和原理
- 四大图片加载框架的使用和原理
- 如何考虑架构设计
- 自定义 View,绘制流程、步骤,
- 事件拦截和分发机制
- 进程间的通信方式
- 应用的创建启动流程
- Handler 是怎么导致内存泄露的
- 设计模式理解问得也多,
- Binder 驱动
- 如果在 onStop 的时候做了网络请求,onResume 的时候怎么恢复?
- Bitmap 使用时候注意什么?
- Bitmap 的 recycler()
- Android 中开启摄像头的主要步骤
- ViewPager 使用细节,如何设置成每次只初始化当前的 Fragment,其他的不初始化?
- 点击事件被拦截,但是想传到下面的 View,如何操作?
- 微信主页面的实现方式
- 微信上消息小红点的原理
- 如何优化自定义 View
- 低版本 SDK 如何实现高版本 api?
- 描述一次网络请求的流程
- HttpUrlConnection 和 okhttp 关系
- Bitmap 对象的理解
- looper 架构
- Activity 上有 Dialog 的时候按 Home 键时的生命周期
- 两个 Activity 之间跳转时必然会执行的是哪几个方法?
- 前台切换到后台,然后再回到前台,Activity 生命周期回调方法。弹出 Dialog,生命值周期回调方法。
- ActivityThread,AMS,WMS 的工作原理
- 自定义 View 如何考虑机型适配
- 自定义 View 的事件
- AstncTask+HttpClient 与 AsyncHttpClient 有什么区别?
- 事件分发中的 onTouch 和 onTouchEvent 有什么区别,又该如何使用?
(三)腾讯社招安卓岗面试经历(凉)
- synchronize 用法,volatile 用法,两者的区别和场景
- 动态权限适配方案,权限组的概念
- 网络请求缓存处理,okhttp 如何处理网络缓存的;图片加载库相关,bitmap 如何处理大图,如一张 30M 的大图,如何预防 OOM
- 进程保活
- listview 图片加载错乱的原理和解决方案,listview 是如何做缓存的?
- https 相关,如何验证证书的合法性,https 中哪里用了对称加密,哪里用了非对称加密,两者的区别?
- Android 系统为什么会设计 ContentProvider,进程共享和线程安全问题
- 提供一种跨进程数据共享的方式:由系统来管理 ContentProvider 的创建、生命周期及访问的线程分配,简化我们在应用间共享数据(进程间通信)的方式。我们只管通过 ContentResolver 访问 ContentProvider 所提示的数据接口,而不需要担心它所在进程是启动还是未启动。
- 更好的数据访问权限管理:ContentProvider 可以对开发的数据进行权限设置,不同的 URI 可以对应不同的权限,只有符合权限要求的组件才能访问到 ContentProvider 的具体操作。
- 微信的聊天数据在本地都是加密处理的(防止 root 了被破解),设计一个类似的本地数据存储系统
- jvm 相关和 GC 回收算法的区别
- Android 相关优化(如内存优化、网络优化、布局优化、电量优化、业务优化)
- EventBus 实现原理和观察者模式在开发中的运用?
- 动态代理模式如何运用?
- App 是如何沙箱化,为什么要这么做?
(四)滴滴社招面试
- 询问项目相关的问题;
- 概述一下 HashMap
- 答:HashMap 是基于哈希表的 Map 接口的非同步实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
- hashmap 原理说一下;
- HashMap 什么时候进行扩容呢?
- 答:当 HashMap 中的元素个数超过数组大小时,就会进行数组扩容。
- https 相关过程说一下;
- 线程安全。synchronized,lock 各种原理
- 如何保证通信安全性?
- 如何实现链表数组?
- 项目经历介绍;
- content-type 有哪些值?
- 常见的响应码有哪些?
- 200:请求成功,浏览器会把响应体内容(通常是 html)显示在浏览器中;
- 404:请求的资源没有找到,说明客户端错误的请求了不存在的资源;
- 500:请求资源找到了,但服务器内部出现了错误;
- 302:重定向,当响应码为 302 时,表示服务器要求浏览器重新再发一个请求,服务器会发送一个响应头 Location,它指定了新请求的 URL 地址;
- UNICODE 和 utf-8 是干什么的,一个中文分别在其中占据多少大小?
- 如何批量发布?
- 应用崩溃了怎么办,如何收集崩溃信息?
- 应用网络不好如何判断?
- 通信如何保证安全?
- android 缓存如何缓存,图片如何缓存,数据如何缓存,缓存机制?
- js 和 android 耦合;
- react native
- kotlin 以及看法;
- flutter
- 算法题:洗牌不回到原来位置;
- 线程锁的区别;
- 同一个锁为什么效率有差别?
- 多态和重载区别
- 多态是建立在重写的基础之上的,是类与类之间的关係,是发生在不同的类之间的,子类重写父类的方法。实现不同的子类,不同的实现形态。多态有 3 个条件:继承、重写和父类引用指向子类对象
- 重载则是类的内部的方法构型上的不同,是发生在同一个类里面的。同一个函数名称,参数不同的多个方法,实现同一类型的功能。
- Hashmap
- Jni
- 设计模式:观察者模式怎么用?
- 说一下自身的优缺点;
- 你对领导期望是?
- 你对滴滴了解有多少?印象如何?说一下你的看法。
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online