如何声明具有多个具有非平凡关系的泛型类型的成员?

2024-02-19

这是我想在我的java代码中编写的内容:

private <A extends Action<R>, R extends Result> MyType<A,R> member;

然而,这是无效的语法。所以我最终写道:

private MyType<? extends Action<? extends Result>, ? extends Result> member;

但这忽略了两个类都派生于的事实Result是相同的。我的类方法都强制执行这种关系,因此我可以确定 MyType 强制执行它,但我仍然必须不安全地进行类型转换member在某些情况下。

更多细节

这是我想要做的事情的精确版本,尽管它要复杂得多:

我希望我能做到:

private <A extends Action<R>, R extends Result> 
    Map< Class<A>, ActionHandler<A,R> > handlers;

相反,我必须这样做:

private Map< Class< ? extends Action<? extends Result> >, 
             ActionHandler<? extends Action<? extends Result>, 
                           ? extends Result> > handlers;

我的方法强制执行所需的关系,如下所示:

public <A extends Action<R>, R extends Result> void addHandler( 
    ActionHandler<A, R> handler ) {
  handlers.put( handler.getActionType(), handler );
}

我想要以下方法:

public <A extends Action<R>, R extends Result> ActionHandler<A, R> 
    findHandler( A action ) {
  return handlers.get( action.getClass() );
}

但这不起作用:我必须添加演员阵容和@SuppressWarnings("unchecked").

我尝试过的事情

我尝试为此目的创建一个新类:

public class MyMap <A extends Action<R>, R extends Result> extends 
    HashMap< Class<A>, ActionHandler<A,R> > { ... }

MyMap< ?, ? > handlers;

但这没用,我还需要演员。


没有干净的方法可以做到这一点。你能做的最好的就是你已经做过的——隐藏Map在强制类型安全的方法后面,并隐藏这些方法中必要的强制转换。

From 有效的Java第二版,第 29 项:“考虑类型安全的异构容器”(其中 Josh Bloch 勾勒出您正在做的事情的一个简单版本,一个“映射”,其中键是类,值是键类的实例):

接下来要注意的是,值类型favorites地图很简单Object。换句话说,Map不保证键和值之间的类型关系。事实上,Java 的类型系统还不足以表达这一点。但我们知道这是真的,当需要检索最喜欢的东西时,我们会利用它。

鉴于无论如何您都无法对值进行任何有用的类型强制,最不混乱的实现可能是这样的:

public class HandlerRegistry
{
    private Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();

    public <R extends Result, A extends Action<R>>
        void addHandler(Class<A> actionClass, ActionHandler<R, A> handler) {
        map.put(actionClass, handler);
    }

    @SuppressWarnings("unchecked")
    public <R extends Result, A extends Action<R>> ActionHandler<R, A>
        findHandler(A action) {
            return (ActionHandler<R, A>) map.get(action.getClass());
    }
}

关于a需要注意的一件事Map基于解决方案:如果action不完全是用作键的类,map.get()不会起作用——例如,如果它是一个子类,或者如果关键类是一个接口并且action本身就是实现。您可能会更好:

    @SuppressWarnings("unchecked")
    public <R extends Result, A extends Action<R>> ActionHandler<R, ? super A>
        findHandler( A action ) {
            for ( Map.Entry<Class<?>, Object> entry : map.entrySet() )
            {
                if (entry.getKey().isAssignableFrom(action.getClass())) {
                    return (ActionHandler<R, ? super A>) entry.getValue();
                }
            }
            return null;
    }

(Note:原来上面的第二个例子返回了ActionHandler<R, A>,这实际上是不正确的——它应该是? super A。 (我们不知道它除了可以处理什么A-- 它可以是任何超类A,一直到Object。)在这种特殊情况下,它可能足够安全,但如果您考虑类似List,我们可能会遇到很多麻烦:你可以安全地放置一个A into a List<? super A>,但如果你假设你只会得到A摆脱它,你会得到ClassCastExceptions.)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何声明具有多个具有非平凡关系的泛型类型的成员? 的相关文章

  • Java中字符串中特殊字符的替换

    Java中如何替换字符串 E g String a adf sdf 如何替换和避免特殊字符 您可以删除除此之外的所有字符可打印的 ASCII 范围 http en wikipedia org wiki ASCII ASCII printab
  • Eclipse 在源代码管理中保存操作

    我们希望找到一种在签入之前执行代码标准的 轻量级 方法 我们真的很喜欢使用 Eclipse 内置的想法保存操作 go to Preferences gt gt Java gt gt Editor gt gt Save Actions 其中有
  • Java:如何从转义的 URL 获取文件?

    我收到了一个定位本地文件的 URL 事实上我收到的 URL 不在我的控制范围内 URL 按照 RFC2396 中的定义进行有效转义 如何将其转换为 Java File 对象 有趣的是 URL getFile 方法返回一个字符串 而不是文件
  • 正则表达式拆分数字和字母组,不带空格

    如果我有一个像 11E12C108N 这样的字符串 它是字母组和数字组的串联 如何在中间没有分隔符空格字符的情况下分割它们 例如 我希望分割结果为 tokens 0 11 tokens 1 E tokens 2 12 tokens 3 C
  • Android在排序列表时忽略大小写

    我有一个名为路径的列表 我目前正在使用以下代码对字符串进行排序 java util Collections sort path 这工作正常 它对我的 列表进行排序 但是它以不同的方式处理第一个字母的情况 即它用大写字母对列表进行排序 然后用
  • java中如何连接字符串

    这是我的字符串连接代码 StringSecret java public class StringSecret public static void main String args String s new String abc s co
  • wait() 在游戏中如何工作?

    在 playframework 的文档中here http www playframework org documentation 1 2 1 asynchronous已写 public static void loopWithoutBlo
  • 当从服务类中调用时,Spring @Transactional 不适用于带注释的方法

    在下面的代码中 当方法内部 是从内部调用的方法外部 应该在交易范围内 但事实并非如此 但当方法内部 直接从调用我的控制器class 它受到事务的约束 有什么解释吗 这是控制器类 Controller public class MyContr
  • 画透明圆,外面填充

    我有一个地图视图 我想在其上画一个圆圈以聚焦于给定区域 但我希望圆圈倒转 也就是说 圆的内部不是被填充 而是透明的 其他所有部分都被填充 请参阅这张图片了解我的意思 http i imgur com zxIMZ png 上半部分显示了我可以
  • hibernate锁等待超时超时;

    我正在使用 Hibernate 尝试模拟对数据库中同一行的 2 个并发更新 编辑 我将 em1 getTransaction commit 移至 em1 flush 之后我没有收到任何 StaleObjectException 两个事务已成
  • Java 8 流 - 合并共享相同 ID 的对象集合

    我有一系列发票 class Invoice int month BigDecimal amount 我想合并这些发票 这样我每个月都会收到一张发票 金额是本月发票金额的总和 例如 invoice 1 month 1 amount 1000
  • 使用 SQLITE 按最近的纬度和经度坐标排序

    我必须获得一个 SQLite SQL 语句 以便在给定初始位置的情况下按最近的纬度和经度坐标进行排序 这是我在 sqlite 数据库中的表的例句 SELECT id name lat lng FROM items EXAMPLE RESUL
  • 很好地处理数据库约束错误

    再一次 它应该很简单 我的任务是在我们的应用程序的域对象中放置一个具有唯一约束的特定字段 这本身并不是一个很大的挑战 我刚刚做了以下事情 public class Location more fields Column unique tru
  • 在游戏视图下添加 admob

    我一直试图将 admob 放在我的游戏视图下 这是我的代码 public class HoodStarGame extends AndroidApplication Override public void onCreate Bundle
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • Java整数双除法混淆[重复]

    这个问题在这里已经有答案了 方案1 int sum 30 double avg sum 4 result is 7 0 not 7 5 VS 方案2 int sum 30 double avg sum 4 0 Prints lns 7 5
  • 欧洲中部时间 14 日 3 月 30 日星期五 00:00:00 至 日/月/年

    我尝试解析格式日期Fri Mar 30 00 00 00 CET 14至 日 月 年 这是我的代码 SimpleDateFormat formatter new SimpleDateFormat dd MM yyyy System out
  • 将 Azure AD 高级自定义角色与 Spring Security 结合使用以进行基于角色的访问

    我创建了一个演示 Spring Boot 应用程序 我想在其中使用 AD 身份验证和授权 并使用 AD 和 Spring Security 查看 Azure 文档 我执行了以下操作 package com myapp contactdb c
  • javafx android 中的文本字段和组合框问题

    我在简单的 javafx android 应用程序中遇到问题 问题是我使用 gradle javafxmobile plugin 在 netbeans ide 中构建了非常简单的应用程序 其中包含一些文本字段和组合框 我在 android
  • GUI Java 程序 - 绘图程序

    我一直试图找出我的代码有什么问题 这个想法是创建一个小的 Paint 程序并具有红色 绿色 蓝色和透明按钮 我拥有我能想到的让它工作的一切 但无法弄清楚代码有什么问题 该程序打开 然后立即关闭 import java awt import

随机推荐