当前位置: 首页 > wzjs >正文

江西网站开发科技公司长春招聘网智联

江西网站开发科技公司,长春招聘网智联,wordpress paginate_links,网站开发前期需要啥泛型擦除 一、基础概念与原理(必问) 问题 1:什么是泛型擦除?它在 Java 中的实现原理是什么? 回答核心: 泛型擦除是 Java 泛型的底层机制,指编译器在编译时会擦除泛型的具体类型信息&#xff0…

泛型擦除

一、基础概念与原理(必问)

问题 1:什么是泛型擦除?它在 Java 中的实现原理是什么?
回答核心
泛型擦除是 Java 泛型的底层机制,指编译器在编译时会擦除泛型的具体类型信息,将泛型参数替换为其上限类型(通常是Object),仅在编译期保留类型检查,运行时类型信息丢失。

  • 实现原理
    1. 类型替换:如List<String>编译后变为List(原始类型),所有T被替换为Object
    2. 桥接方法:当子类泛型类型与父类不同时,编译器生成桥接方法(如setSrc(Object))以维持多态性。
    3. 兼容性:确保泛型代码能在旧版本 JVM 上运行。

示例

List<String> list = new ArrayList<>();
list.add("Android");
// 编译后,list的类型被擦除为List,运行时无法区分String与Integer类型
二、Android 开发中的典型场景(高频考点)

问题 2:泛型擦除在 Android 开发中会引发哪些问题?如何解决?
回答核心

  1. 运行时类型丢失:无法通过反射直接获取泛型参数类型。

    • 解决方案:使用TypeToken(如 Gson)或子类化保留类型信息。
      // Gson中解析List<String>
      Type type = new TypeToken<List<String>>() {}.getType();
      List<String> list = gson.fromJson(json, type);
      
  2. 泛型数组初始化限制

    • 错误示例T[] array = new T[10];(编译错误)。
    • 解决方案:手动强制转换Object[]数组。
  3. 方法重载冲突:子类无法通过泛型参数重载父类方法。

    • 错误示例
      class Parent<T> {public void method(T param) {} // 擦除后为method(Object)
      }
      class Child extends Parent<String> {public void method(String param) {} // 编译错误:与父类方法签名冲突
      }
      
    • 解决方案:通过接口或通配符(?)定义方法。
三、框架与工具的实战应用(重点)

问题 3:Gson 如何处理泛型擦除?请举例说明。
回答核心
Gson 通过TypeToken解决泛型擦除问题。TypeToken利用匿名内部类保留泛型类型信息,通过反射获取实际类型。

  • 示例
    // 解析嵌套泛型类型List<Map<String, Integer>>
    Type type = new TypeToken<List<Map<String, Integer>>>() {}.getType();
    List<Map<String, Integer>> result = gson.fromJson(json, type);
    
  • 原理:匿名内部类的父类泛型信息被记录在 Class 文件的Signature属性中,通过反射可获取。

问题 4:Kotlin 如何解决泛型擦除?
回答核心
Kotlin 通过reified关键字(配合inline函数)实化泛型,在运行时保留类型信息。

  • 示例
    inline fun <reified T> fetchData(): T {val type = T::class.java// 使用反射或网络请求获取数据return data as T
    }
    // 调用时直接获取具体类型
    val result = fetchData<Result>()
    
  • 原理inline函数在编译时将函数体替换到调用处,reified确保泛型类型被保留。
四、反射与泛型擦除的深度交互(难点)

问题 5:在 Android 中,如何通过反射获取泛型字段的实际类型?
回答核心
通过ParameterizedType接口解析泛型信息。

  • 示例
    class MyClass<T> {private List<T> data;
    }
    // 获取data字段的泛型类型
    Field field = MyClass.class.getDeclaredField("data");
    Type genericType = field.getGenericType();
    if (genericType instanceof ParameterizedType) {Type actualType = ((ParameterizedType) genericType).getActualTypeArguments()[0];System.out.println("实际类型:" + actualType.getTypeName()); // 输出T的具体类型
    }
    
  • 注意:需处理Type的多层嵌套(如List<Map<String, ?>>)。
五、面试官高频追问(陷阱题)

追问 1:泛型擦除如何影响类型安全?
回答
编译期保证类型安全,但运行时类型信息丢失可能导致ClassCastException。例如,通过反射向List<String>中插入Integer会绕过编译检查,运行时崩溃。

追问 2:为什么 Java 不支持泛型数组?
回答
泛型数组在运行时无法保留类型信息,可能导致内存安全问题。例如:

List<String>[] array = new List<String>[10]; // 编译错误
array[0] = new ArrayList<Integer>(); // 运行时将引发ClassCastException

追问 3:Retrofit 如何处理泛型擦除?
回答
Retrofit 通过ParameterizedType解析方法返回值的泛型类型。例如,Call<Result<T>>的泛型信息被记录在方法的Signature属性中,通过反射获取并传递给 Gson 进行序列化。

synchronized 底层原理

底层实现原理
  • 对象头:在 Java 中,每个对象都有一个对象头(Object Header),对象头中包含了一些与锁相关的信息,如锁状态、哈希码、分代年龄等。锁状态有四种:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。
  • 偏向锁:偏向锁是为了在无竞争的情况下减少锁的开销。当一个线程第一次访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程 ID,以后该线程在进入和退出同步块时不需要进行 CAS 操作来加锁和解锁,只需要简单地测试一下对象头的 Mark Word 里是否存储着指向当前线程的偏向锁。如果测试成功,表示线程已经获得了锁。如果测试失败,则需要查看 Mark Word 中偏向锁的标识是否设置成 1(表示当前是偏向锁):如果没有设置,则使用 CAS 竞争锁;如果设置了,则尝试使用 CAS 将对象头的偏向锁指向当前线程。
  • 轻量级锁:当多个线程交替执行同步块时,偏向锁会升级为轻量级锁。线程在执行同步块之前,JVM 会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头中的 Mark Word 复制到锁记录中,官方称为 Displaced Mark Word。然后线程尝试使用 CAS 将对象头中的 Mark Word 替换为指向锁记录的指针。如果成功,当前线程获得锁;如果失败,表示其他线程已经竞争到锁,当前线程会尝试自旋等待锁的释放。
  • 重量级锁:如果自旋次数达到一定阈值或者有多个线程同时竞争锁,轻量级锁会升级为重量级锁。重量级锁依赖于操作系统的互斥量(Mutex),线程会被阻塞,进入等待队列,当锁被释放时,操作系统会唤醒等待队列中的线程继续竞争锁。

锁的分类

1. 乐观锁 vs 悲观锁
  • 悲观锁(如 synchronized、显式锁 ReentrantLock):
    • 假设竞争激烈,每次访问共享资源前先加锁,确保独占访问。
    • 包含上述偏向锁、轻量级锁、重量级锁(均为悲观锁的不同优化形态)。
  • 乐观锁(如 CAS):
    • 假设竞争较少,不加锁而是直接尝试操作,失败时重试(无锁编程)。
    • 缺点:存在 ABA 问题(需通过 AtomicStampedReference 解决)。
2. 公平锁 vs 非公平锁
  • 公平锁:线程按申请顺序获取锁(如 ReentrantLock(true)),减少 “饥饿” 但增加上下文切换开销。
  • 非公平锁:允许刚释放的锁被任意线程抢占(如 synchronizedReentrantLock(false)),效率更高但可能导致部分线程长时间等待。
3. 可重入锁 vs 不可重入锁
  • 可重入锁:同一线程可多次获取同一把锁(如 synchronizedReentrantLock),通过计数器记录重入次数,避免死锁。
    public synchronized void method1() {method2(); // 可重入,无需再次竞争锁
    }
    public synchronized void method2() {}
    
  • 不可重入锁:未实现重入逻辑(如早期 Java 版本的 synchronized 非显式实现,现几乎不用)。

CAS 的缺点及解决办法

1. ABA 问题
  • 问题描述:CAS 操作在比较和交换时,会检查变量的值是否与预期值相同。如果一个变量的值从 A 变为 B,再从 B 变回 A,CAS 操作会认为变量的值没有发生变化,从而继续执行更新操作,但实际上变量的值已经发生了变化,这可能会导致一些意外的结果。
  • 解决办法:使用带有版本号的原子引用类 AtomicStampedReference 或 AtomicMarkableReferenceAtomicStampedReference 会在更新值的同时更新版本号,每次更新时会检查值和版本号是否都与预期值相同;AtomicMarkableReference 则是使用一个布尔值来标记变量是否被修改过。
import java.util.concurrent.atomic.AtomicStampedReference;public class ABAExample {private static AtomicStampedReference<Integer> atomicStampedRef = new AtomicStampedReference<>(100, 0);public static void main(String[] args) {Thread t1 = new Thread(() -> {int stamp = atomicStampedRef.getStamp();System.out.println("Thread 1 stamp: " + stamp);atomicStampedRef.compareAndSet(100, 101, stamp, stamp + 1);atomicStampedRef.compareAndSet(101, 100, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1);});Thread t2 = new Thread(() -> {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}int stamp = atomicStampedRef.getStamp();System.out.println("Thread 2 stamp: " + stamp);boolean result = atomicStampedRef.compareAndSet(100, 102, stamp, stamp + 1);System.out.println("Thread 2 update result: " + result);});t1.start();t2.start();}
}
2. 循环时间长开销大
  • 问题描述:如果 CAS 操作长时间不成功,线程会一直自旋,会消耗大量的 CPU 资源。
  • 解决办法:可以设置自旋的最大次数,当达到最大次数后,线程放弃自旋,进入阻塞状态。另外,也可以使用锁机制,当 CAS 操作失败时,使用传统的锁来保证线程同步。
3. 只能保证一个共享变量的原子操作
  • 问题描述:CAS 操作只能对一个共享变量进行原子操作,如果需要对多个共享变量进行原子操作,CAS 就无法满足需求。
  • 解决办法:可以使用 AtomicReference 类将多个共享变量封装成一个对象,然后对这个对象进行 CAS 操作。另外,也可以使用锁机制来保证多个共享变量的原子性。
import java.util.concurrent.atomic.AtomicReference;class Pair {int x;int y;public Pair(int x, int y) {this.x = x;this.y = y;}
}public class MultiVariableCASExample {private static AtomicReference<Pair> atomicPair = new AtomicReference<>(new Pair(0, 0));public static void main(String[] args) {Pair expected = atomicPair.get();Pair newPair = new Pair(1, 1);boolean result = atomicPair.compareAndSet(expected, newPair);System.out.println("Update result: " + result);}
}

文章转载自:

http://Gd3MN752.yrjkz.cn
http://cvxnY8Nd.yrjkz.cn
http://ovfgd4fe.yrjkz.cn
http://QlSFmtKI.yrjkz.cn
http://qKaRBbai.yrjkz.cn
http://ZFFGoZB4.yrjkz.cn
http://CT9dkD1y.yrjkz.cn
http://k3D2eEjQ.yrjkz.cn
http://w9JHjVEV.yrjkz.cn
http://qjdd9nC7.yrjkz.cn
http://imhNzjHP.yrjkz.cn
http://zE7l3sOJ.yrjkz.cn
http://mGV7JdvH.yrjkz.cn
http://C2OSPC50.yrjkz.cn
http://tmlCUsTV.yrjkz.cn
http://WSyIvpwj.yrjkz.cn
http://9yhWNwuU.yrjkz.cn
http://OIR3cGDE.yrjkz.cn
http://39qPZx5k.yrjkz.cn
http://sIgE0Cr2.yrjkz.cn
http://uzf3jgBa.yrjkz.cn
http://V5GABEV1.yrjkz.cn
http://SiIz0wVM.yrjkz.cn
http://CBz9zL9p.yrjkz.cn
http://Btp8Cknj.yrjkz.cn
http://a35Q5qwH.yrjkz.cn
http://8ZH7DYhc.yrjkz.cn
http://eEVII1hV.yrjkz.cn
http://ty6xEMfC.yrjkz.cn
http://ADqFNB5G.yrjkz.cn
http://www.dtcms.com/wzjs/745869.html

相关文章:

  • 嘉定网站设计制作优化排名深圳建设行业网站
  • 同性恋色做视频网站计算机毕设代做网站
  • 网站建立的流程大连开发区社保网站
  • 企业产品做哪个网站推广好做变性手术视频网站
  • 网站服务器物理地址怎么查网站优化就是seo
  • 无锡网站建设收费wordpress显示访问量
  • 专业做网站服务wordpress要更新
  • 网站建设如何创建框架页面惠州市建网站公司
  • 做最好的在线看片网站文案转行做网站编辑
  • 网站建设的基本步骤金华公司做网站
  • 网站的后台管理员系统建设教程做网站需要注意
  • 郑州区块链数字钱包网站开发过程公司做百度网站要多少钱
  • 建设部网站质量终身责任承诺书百度高级检索入口
  • 做介绍的英文网站珠海建站服务
  • 孝南区建设局网站c2c的含义分别是什么
  • 北京市建设规划网站通付盾 网站建设公司
  • 个人网站的色彩设计怎么做宣传片拍摄哪个好
  • 泉州企业网站维护定制网页设计尺寸代码
  • 手机建站的网站有哪些深圳写字楼崩溃求助
  • 清远佛冈住房和城乡建设局网站中国网站建设新闻
  • 怎么做网站导航外链外包做网站不付尾款
  • 做网站会员登陆开县网站建设
  • wordpress增加视频播放西安seo黑
  • 套模版做的网站好优化吗网站建设费用还是网络专业
  • jsp和html做的招聘网站做国外直播网站
  • 地名网站建设方案wordpress分享到微博才能看到
  • 外贸网站建设哪个好昆明做网站公司哪家好
  • 温州做网站建设多少钱html5旅游网站
  • [ 1500元做网站_验收满意再付款! ]_沛县网络公司彩票网站开发周期
  • 泰州网站建设托管做网站的好处和坏处