泛型擦除与多态的冲突与解决方法

简介: 泛型类 `Pair<T>` 在类型擦除后,其泛型变为 `Object`,子类 `DateInter` 重写 `setValue(Date)` 和 `getValue()` 时,实际覆盖的是原始方法。由于擦除后父类方法参数为 `Object`,子类 `Date` 方法看似重写,实为桥接方法实现的“伪重载”。编译器生成桥接方法以保证多态,虚拟机通过签名区分方法,实现泛型多态性。

假设有一个泛型类
class Pair {

private T value;  

public T getValue() {  
    return value;  
}  

public void setValue(T value) {  
    this.value = value;  
}  

}
然后有一个子类需要继承
class DateInter extends Pair {

@Override  
public void setValue(Date value) {  
    super.setValue(value);  
}  

@Override  
public Date getValue() {  
    return super.getValue();  
}  

}
在这个子类中,我们设定父类的泛型类型为Pair,在子类中,我们覆盖了父类的两个方法,我们的原意是这样的:将父类的泛型类型限定为Date,那么父类里面的两个方法的参数都为Date类型。
所以,我们在子类中重写这两个方法一点问题也没有,实际上,从他们的@Override标签中也可以看到,一点问题也没有,实际上是这样的吗?
分析:实际上,类型擦除后,父类的的泛型类型全部变为了原始类型Object,所以父类编译之后会变成下面的样子:
class Pair {
private Object value;

public Object getValue() {  
    return value;  
}  

public void setValue(Object  value) {  
    this.value = value;  
}  

}
而此时,子类中类型依然是Date,这如果还是在继承关系中,那么根本就不是重写,而是重载了。通过反编译会发现子类中的方法Object getValue()和Date getValue()是同 时存在的,可是如果是常规的两个方法,他们的方法签名是一样的,也就是说虚拟机根本不能分别这两个方法。如果是我们自己编写Java代码,这样的代码是无法通过编译器的检查的,但是虚拟机却是允许这样做的,因为虚拟机通过参数类型和返回类型来确定一个方法,所以编译器为了实现泛型的多态允许自己做这个看起来“不合法”的事情,然后交给虚拟器去区别。

相关文章
|
2月前
|
存储 NoSQL 物联网
MongoDB应用场景
MongoDB适用于社交、游戏、物流、物联网及直播等场景,因其支持海量数据存储、高频读写操作。用户信息、动态、日志等低事务性、高并发数据可高效存取,尤其适合用嵌套结构与地理位置索引优化查询,是大规模非结构化数据存储的理想选择。(238字)
|
2月前
|
安全 小程序 JavaScript
OAuth2.0四种授权模式
OAuth2四种授权模式简介:授权码模式最安全,适用于第三方登录;简化模式无授权码,token直接返回,适合无后端场景;密码模式需用户共享账号信息,仅限高度信任服务;客户端模式为服务间调用,无需用户参与。
|
2月前
|
存储 关系型数据库 MySQL
业务应用场景
传统关系型数据库(如MySQL)难以应对“三高”挑战:高并发读写、海量数据存储访问,以及高可扩展性与高可用性需求,在Web2.0时代面临性能与扩展瓶颈。
|
2月前
|
Java
常见加载顺序
本示例展示了Java中各类代码块的执行顺序:静态代码块随类加载仅执行一次,优先于main方法;局部代码块在方法内按顺序执行;构造代码块每次创建对象前执行,再调用构造器。输出顺序体现其优先级与生命周期。
|
2月前
|
安全 Java 网络架构
SpringSecurity核心架构
Spring Security基于过滤器链实现安全控制,核心为FilterChainProxy,通过DelegatingFilterProxy集成到容器。多SecurityFilterChain按请求路径匹配,ExceptionTranslationFilter处理认证与授权异常,实现细粒度访问控制。(238字)
|
2月前
|
前端开发 开发者
什么是跨域
CORS需浏览器与服务器共同支持,所有现代浏览器均兼容(IE≥10)。通信由浏览器自动完成,开发者无需特殊处理。关键在于服务器需实现CORS接口。请求分为简单和非简单两类,区别在于请求方法和头信息的限制,浏览器会自动处理跨域细节。
|
2月前
|
SQL 数据库 数据安全/隐私保护
用于绕过身份验证的 SQL 注入示例
SQL注入可绕过登录验证,攻击者通过提交恶意构造的用户名(如admin&#39;)--)和空密码,利用注释符使数据库忽略密码校验,从而非法登录。该技术依赖应用缺乏输入验证,凸显严格过滤与参数化查询的重要性。(238字)
|
2月前
|
缓存 Java
线程池初始化严禁使用Executors
阿里巴巴代码规范禁止使用Executors创建线程池,因易导致OOM。推荐手动创建ThreadPoolExecutor,合理设置参数,避免资源耗尽风险。
|
2月前
|
Java 数据库连接 mybatis
映射关系
MyBatis中通过resultMap实现一对一、一对多、多对一及多对多映射。一对一用于属性与字段映射;一对多通过`&lt;collection&gt;`关联主表与子表集合;多对一使用`&lt;association&gt;`关联对象;多对多借助中间类实现双向集合映射,灵活处理复杂关系数据。
|
2月前
|
存储 安全 Java
OAuth2.0使用场景
A网站需打印用户存于B网站的照片时,传统方式需共享账号密码,而OAuth2只需获取临时通行令牌,按需授权资源访问权限,更安全灵活。注意:OAuth2侧重服务间资源授权,不同于单点登录。Spring Security集成OAuth2可实现资源共享与单点登录。

热门文章

最新文章