概述
以前就了解过Java泛型的实现是不完整的,最近在做一些代码重构的时候遇到一些Java泛型类型擦除的问题,简单的来说,Java泛型中所指定的类型在编译时会将其去除,因此List 和 List 在编译成字节码的时候实际上是一样的。因此java泛型只能做到编译期检查的功能,运行期间就不能保证类型安全。我最近遇到的一个问题如下:
假设有两个bean类
/** Test. */ @Data @NoArgsConstructor @AllArgsConstructor public static class Foo { public String name; } /** Test. */ @Data @NoArgsConstructor @AllArgsConstructor public static class Dummy { public String name; }
以及另一个对象
@NoArgsConstructor @AllArgsConstructor @Data public static class Spec<T> { public String spec; public T deserializeTo() throws JsonProcessingException { var mapper = new ObjectMapper(); return (T) mapper.readValue(spec, Foo.class); } }
可以看到 Spec
对象中保存了以上两种类型json序列化后的字符串,并提供了方法将string spec 反序列化成相应的类型,比较理想的方式是在反序列化的方法中能够获取到参数类型 T 的实际类型,理论上运行时Spec类型是确定了,因此T也应该是确定的,但是因为类型擦除,所以实际上获取不到他的类型。
按照以下尝试 通过 ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()
获取泛型类型,经过测试是获取不到的
@Test public void test() throws JsonProcessingException { var foo = new Foo("foo"); var spec = new Spec<Foo>(mapper.writeValueAsString(foo)); var deserialized = spec.deserializeTo(); Assertions.assertTrue(deserialized instanceof Foo); } @NoArgsConstructor @AllArgsConstructor @Data public static class Spec<T> { public String spec; private Class<T> getSpecClass() { return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; } public T deserializeTo() throws JsonProcessingException { var mapper = new ObjectMapper(); System.out.println(spec); return (T) mapper.readValue(spec, getSpecClass()); } }
会有以下的错误
java.lang.ClassCastException: class java.lang.Class cannot be cast to class java.lang.reflect.ParameterizedType (java.lang.Class and java.lang.reflect.ParameterizedType are in module java.base of loader 'bootstrap')
有两种办法来绕过这个问题
第一种比较简单,就是在创建spec对象时,直接把类型的class传进来,这样就可以直接使用。
第二种是创建spec的子类中使用这个方法就可以获取泛型的类型
@Data public abstract static class AbstractSpec<T> { public String spec; public AbstractSpec(String spec) { this.spec = spec; } private Class<T> getSpecClass() { return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; } public T deserializeTo() throws JsonProcessingException { var mapper = new ObjectMapper(); System.out.println(spec); return (T) mapper.readValue(spec, getSpecClass()); } } public static class Spec extends AbstractSpec<Foo> { public Spec(String spec) { super(spec); } } @Test public void test() throws JsonProcessingException { var foo = new Foo("foo"); var spec = new Spec(mapper.writeValueAsString(foo)); var deserialized = spec.deserializeTo(); Assertions.assertTrue(deserialized instanceof Foo); }
这里spec类就可以顺利的被反序列化。
这个和最开始失败的case的差别就是新增了一个子类,主要的差别是getGenericSuperclass的返回值有差异,非子类的情况下,获取到的是Object。
因此理论上子类Spec的类型信息中,实际上是保存了父类中的类型参数信息的,也就是例子中的Foo. 按照 reflection - getGenericSuperclass() in Java. How does it work? - Stack Overflow 的方式,可以查看到Spec类的字节码中有相应的类型信息。
$ javap -verbose ./org/apache/flink/kubernetes/operator/controller/GenericTest$Spec.class | grep Signature #15 = Utf8 Signature Start Length Slot Name Signature Signature: #19 // Lorg/apache/flink/kubernetes/operator/controller/GenericTest$AbstractSpec<Lorg/apache/flink/kubernetes/operator/controller/GenericTest$Foo;>;
见过真正头铁的程序员吗?如题所示,真人真事,这位二本的兄弟在这短短几个月内海投了638份简历,全挑的大厂岗位投的,仅字节跳动就前前后后面试了九次,他说:没有撤退可言。
九次面试经历也是奇了——
网友们的评论真相了:
“字节这么缺人?大家可以去投了”
“看来字节跳动就是要定你了!”
“哥们你这得累积多少大厂面试经验啊!快点传授一波!”
“我的天哪,638份简历,9次字节面试,吾辈楷模。”
真正的海量面经(文末有解析)!问及面试考题,这位兄弟言辞中有些许惭愧:面试官已经给了一些提示,但无奈自己准备得不充分,回答很不理想。他没想到,像Redis,Spring,JVM,Zookeeper等这些在工作中都有涉及过的技术,面试官会问的这么深入!
一、网络原理
-
OSI 与 TCP/IP 各层的结构与功能,都有哪些协议
-
TCP 建立连接的过程,为什么要三次握手?
-
TCP、UDP 协议的区别,各自的应用场景
-
打开浏览器,输入 URL 地址,访问主页的过程
-
HTTP 有哪些方法?
-
HTTP 和 HTTPS 有什么区别?
二、Java 核心技术
-
HashMap 底层数据结构是什么,时间复杂度多少?
-
JDK 8 中对 HashMap 做了怎样的优化?
-
HashMap 和 TreeMap 什么区别?
-
ConcurrentHashMap 的实现原理
-
包装类的缓存机制如何应用
-
Error 和 Exception 有什么区别?
-
通过一个例子描述下 BIO、NIO、AIO 三者的区别?
-
动态代理实现有几种方式?
-
阐述 JDBC 操作数据库的步骤?
-
Lambda 表达式有哪些应用?
三、Java 并发编程
-
线程有哪几种状态?
-
创建线程池需要指定什么参数?
-
线程池底层如何实现,工作原理怎样?
-
volatile 的实现原理是什么?
-
Synchronized 和 Lock 什么区别?
-
Java 中有哪些锁?有什么区别?
-
Synchronized 锁升级的原理是什么?
-
使用 ThreadLocal 有哪些注意事项?
-
CAS 如何实现的?
-
Thread 类的 sleep() 方法和对象的 wait() 方法都可以让线程暂停执行,它们有什么区别?
-
守护线程是什么?
-
说一下 Atomic 的原理?
-
如何用 Java 实现生产者消费者?
-
Java 内存模型是什么?
-
JMM 在并发中有什么应用?
四、Java 虚拟机
-
描述一下 JVM 的内存结构?
-
Java 8 的内存分化有哪些改进?
-
有哪些对象分配规则?
-
Java 对象创建过程
-
描述 JVM 加载 class 文件的机制?
-
双亲委派模型是什么?
-
字节码是什么?字节码增强有哪些?
-
JVM 有哪些编译优化?
-
常见的垃圾回收算法和收集器有哪些?
-
如何打印虚拟机堆栈信息?
五、Spring 系列
-
什么是 AOP,AOP 的作用是什么?
-
如何理解 Spring 的 IOC 和 DI?
-
CGLIB 和 JDK 动态代理什么区别?
-
Spring Boot 支持哪些嵌入式容器,如何配置?
六、数据库
-
MySQL 中 MyISAM 与 InnoDB 引擎的区别
-
MySQL InnoDB 的默认隔离级别是什么?
-
举一个数据库死锁的例子,MySQL 怎么解决死锁?
-
MySQL InnoDB 存储的文件结构,为什么使用 B-Tree(B+Tree)?
-
索引的类型有哪些?
-
如何创建合理的索引,索引如何优化?
-
索引失效有哪几种情况?
-
…
七、分库分表
-
为什么要分库分表?
-
如何解决分库分表主键问题?
-
分库分表有哪些中间件,有什么优点和缺点?
-
…
八、分布式缓存
-
怎么保证缓存与数据库的双写一致性
-
Redis 新版本支持多线程,性能怎么样?
-
Redis 有什么数据类型,都在哪些场景下使用?
-
Redis 的高可用有哪些机制?
-
Redis 的持久化有哪些方式?
-
Redis 过期策略都有哪些?
-
写一下 Java 版本的 LRU 代码?
九、分布式服务框架
-
Dubbo 的架构和服务调用过程怎样?
-
注册中心挂了可以继续通信吗?
-
ZooKeeper 的原理是什么?
-
Dubbo 支持哪些序列化协议?
十、分布式消息队列
-
消息队列有什么作用?
-
如何保证消息队列的高可用?
-
如何保证消息不被重复消费?
-
不同消息队列的选型和对比
十一、分布式系统
-
CAP 理论是什么?
-
Base 理论是什么?
-
数据一致性有哪几种?
-
分布式事务有哪些解决方案?
-
如何使用 Redis 实现分布式锁?
-
负载均衡有哪些常见策略?
看完你能回答上几道?据我所知,如果能回答的出其中的一半,就算是勉强及格了。如果都答对你都能全部回答出来,那你应该是妥妥的技术大牛了!可以放心去投大厂简历了!
但如果你没办法完全答出这些问题,我也在这整理互联网大厂常问高频面试解析及Java后端进阶学习笔记及配套视频分享给大家!由于篇幅原因,本文只展示了目录和内容截图,有需要学习的小伙伴戳下方地址来学习吧!
01 Java快速面试指南
02 Java从入门到架构成长笔记
Java基础篇
三大框架篇
项目经验篇(秒杀+SpringBoot实战)
打怪升级第一步—开发1到3年
并发编程篇
JVM及调优篇
网络编程篇
MySQL调优篇
设计模式篇
Spring源码篇
MyBatis源码篇
打怪升级第二步:4-5年资深高开
分布式监控
消息队列
分布式存储
打怪升级第三步:5到7年架构进阶
性能调优实战笔记
大厂分布式场景实战笔记
03 跳槽解析,简历解析
总结
虽然面试套路众多,但对于技术面试来说,主要还是考察一个人的技术能力和沟通能力。不同类型的面试官根据自身的理解问的问题也不尽相同,没有规律可循。 有些面试官喜欢问自己擅长的问题,比如在实际编程中遇到的或者他自己一直在琢磨的这方面的问题,还有些面试官,尤其是大厂的比如 BAT 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。更多资料可关注下方公众号免费获取!
最后
以上就是秀丽小虾米为你收集整理的Java泛型类型擦除问题二、Java 核心技术三、Java 并发编程四、Java 虚拟机五、Spring 系列六、数据库七、分库分表八、分布式缓存九、分布式服务框架十、分布式消息队列十一、分布式系统01 Java快速面试指南03 跳槽解析,简历解析的全部内容,希望文章能够帮你解决Java泛型类型擦除问题二、Java 核心技术三、Java 并发编程四、Java 虚拟机五、Spring 系列六、数据库七、分库分表八、分布式缓存九、分布式服务框架十、分布式消息队列十一、分布式系统01 Java快速面试指南03 跳槽解析,简历解析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复