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

Java 类型转换和泛型原理(JVM 层面)

一、类型转换

概念解释:

编译类型:在编译时确定,保存在虚拟机栈的栈帧中的局部变量表中;

运行类型:在运行时确定,由保存在局部变量表中变量指向的堆中对象实例的类型决定(存储在对象头中);

合法性:运行类型必须是变量类型本身或其子类,否则会抛出 ClassCastException 等异常

在进行强制类型转换时,做的操作非常简单,检查被转换的变量指向的堆中实例类型和转换后的类型是否合法

// 向上转向,安全的(子类包含父类的所有信息)
// animal 的编译类型是 Animal,运行类型是 Dog
Animal animal = new Dog(); 
// 向下转型,将animal引用转换为Dog类型的引用
Dog dog = (Dog) animal; 

二、泛型

Java 泛型的底层原理是通过 泛型擦除 实现的。

  1. 编译时进行类型检查;
  2. 编译时将泛型类型擦除,替换为对应的边界类型(未指定时替换为 Object)
    1. 例如:List<T> -> List<Object>、List<T extends Animal> -> List<Animal>
      1. 也就是说 JVM 堆中的对象实例中的类型是替换后的类型;

    2. 为什么需要擦除:泛型是在 JDK 1.5 中引入的,擦除是为了兼容性;
  3. 编译时插入强制类型转换代码
Box<String> box = new Box<>();
box.set("Hello");
String str = box.get();// 编译时生成强制类型转换代码
String str = (String) box.get();

Java 中的泛型并不是真正的泛型,因为在运行是,泛型被擦除了。

而 C++ 中通过模板的方式,在创建泛型类时,会创建和传入的类型相同的类实例。

// 模板
template <typename T>
T add(T a, T b) {return a + b;
}int result1 = add(1, 2); // 实例化为 add<int>
double result2 = add(1.5, 2.5); // 实例化为 add<double>// 编译器生成两份独立的代码
int add<int>(int a, int b) { return a + b; }
double add<double>(double a, double b) { return a + b; }

http://www.mrgr.cn/news/97268.html

相关文章:

  • 19.go日志包log
  • MessageQueue --- RabbitMQ WorkQueue and Prefetch
  • (二)RestAPI 毛子(Tags——子实体/异常处理/验证/Search/Sort功能)
  • ROS Master多设备连接
  • 【计算机网络】Linux配置SNAT策略
  • Kubernetes 集群搭建(一):k8s 从环境准备到 Calico 网络插件部署(1.16版本)
  • T113s3远程部署Qt应用(dropbear)
  • 通过枚举、AOP、注解、反射填充公共字段
  • 在线记事本——支持Markdown
  • JavaScript基础--01-JS简介
  • 数据蒸馏:Dataset Distillation by Matching Training Trajectories 论文翻译和理解
  • 【Python基础】循环语句(2215字)
  • DDPM 做了什么
  • Go语言-初学者日记(七):用 Go 写一个 RESTful API 服务!
  • JavaScript基础--09-流程控制语句:选择结构(if和switch)
  • Windows 安装和使用 ElasticSearch
  • Python实现ssh自动连接
  • 【双维畅聊】网页版聊天室测试报告
  • 服务器磁盘io性能监控和优化
  • 道路裂缝数据集CrackForest-156-labelme