Java 强制取消选中呼叫

Java 强制取消选中呼叫,java,generics,javac,Java,Generics,Javac,有时,当使用Java反射或某些特殊的对象存储操作时,最终会出现未检查的警告。我已经习惯了,当我对此无能为力时,我会记录下为什么一个电话是未经检查的,为什么它应该被认为是安全的 但是,这是我第一次在一个未经检查的通话中出错。此功能: public <K,V extends SomeClass & SomeOtherClass<K>> void doSomethingWithSomeMap (Map<K,V> map, V data); 会给我一个未经检

有时,当使用Java反射或某些特殊的对象存储操作时,最终会出现未检查的警告。我已经习惯了,当我对此无能为力时,我会记录下为什么一个电话是未经检查的,为什么它应该被认为是安全的

但是,这是我第一次在一个未经检查的通话中出错。此功能:

public <K,V extends SomeClass & SomeOtherClass<K>> void doSomethingWithSomeMap (Map<K,V> map, V data);
会给我一个未经检查的电话警告。Jikes发出警告,但javac给了我一个错误:

Error: <K,V>doSomethingWithSomeMap(java.util.Map<K,V>,V) in SomeClass cannot be applied to (java.util.Map,SomeClass) 错误:SomeClass中的doSomethingWithSomeMap(java.util.Map,V)无法应用于(java.util.Map,SomeClass) 有没有办法用警告来强制它编译


谢谢。

请尝试明确指定:

//Type2 is subclass of (or implements) SomeClass
Map<Type1, Type2> someMap = ...;
SomeClass someData = ...;
<Type1, Type2>doSomethingWithSomeMap(someMap, someData);
//Type2是SomeClass(或实现)的子类
映射someMap=。。。;
SomeClass someData=。。。;
doSomethingWithSomeMap(someMap,someData);

您可以指定V的第二个边界来扩展其他类。但我假设某个类没有实现另一个类(如果实现了,您就不需要多个边界)。所以有些数据不符合这个界限,因此编译器错误。变量someData需要属于一个既扩展了SomeClass又实现了SomeOtherClass的类。

您自己在什么巫毒中:)从问题和注释中,我假设您确信您拥有扩展抽象类
SomeClass
的对象,并且还实现了接口
SomeOtherClass
如果是这种情况,我建议层次结构中的中间抽象类共享这些属性

public abstract class Foo<K> extends SomeClass implements SomeOtherClass<K> {
  ...
}
公共抽象类Foo扩展SomeClass实现SomeOtherClass{
...
}
这样,您可以将静态方法签名简化为:

public <K,V extends Foo<K>> void doSomethingWithSomeMap (Map<K,V> map, V data);
public void doSomethingWithSomeMap(地图地图,V数据);
如果您不想更改当前的对象层次结构,可以使用另一个级别的间接寻址来愚弄编译器

“计算机科学中的所有问题都可以解决 由另一个级别的 间接的。”——大卫·惠勒

公共抽象类SomeClass{
公开摘要无效方法1();
}
其他类的公共接口{
无效方法2(K值);
}
公共类MyClass扩展SomeClass实现SomeOtherClass{
@凌驾
公共无效方法1(){
System.out.println(“MyClass.method1”);
}
@凌驾
公共void方法2(整数值){
System.out.println(“MyClass.method2(“+value+”));
}
}
公共类间接扩展SomeClass实现SomeOtherClass{
私有最终客体客体价值;
公共间接寻址(最终对象值){
this.objectValue=value;
}
@凌驾
公共无效方法1(){
((SomeClass)objectValue.method1();
}
@凌驾
公共无效方法2(K值){
@抑制警告(“未选中”)
SomeOtherClass委托=((SomeOtherClass)objectValue);
方法2(值);
}
}
公共静态void main(字符串[]args){
Map someMap=newhashmap();
SomeClass someData=新MyClass();
间接寻址a=新的间接寻址(someData);
doSomethingWithSomeMap(someMap,a,12);
}
公共静电
void doSomethingWithSomeMap(Map Map,V数据,K值){
data.method1();
数据处理方法2(数值);
}
这将打印:

MyClass.method1
MyClass.method2(12)


您已经知道问题在于
someData
的类型。不幸的是,Java目前不允许您将交叉点类型
SomeClass&SomeOtherClass
用作声明变量的类型,也不允许将其用作cat目标

但是有一种不太完美的方法可以做到这一点,方法是引入一个伪类型变量
X扩展SomeClass&SomeOtherClass
,然后声明
X someData

这应该在反射生成要分配给
someData
的值的方法上完成。未经检查的强制转换
(X)
将是必要的,这是可证明安全的

总的来说,是这样的:

public <X extends SomeClass & SomeOtherClass>
void doReflectionMagic() {
    Map someMap = ...;
    X someData = (X) ...;
    doSomethingWithSomeMap(someMap, someData);
}
公共
void doReflectionMagic(){
映射someMap=。。。;
X someData=(X)。。。;
doSomethingWithSomeMap(someMap,someData);
}

为什么不能将参数
Map
设置为通用?你有一个通用的方法,所以我不明白你为什么不能一直走下去。(编辑:但现在我发现这不是问题的重点,所以请随意忽略。)实际上,此函数执行一些复杂的类型检查,在大多数情况下非常有用。但是,在一个特定的情况下,我需要稍后用反射操作的一些结果来调用它。目前我唯一能找到的解决方法是用someMap制作一个安全和不安全的doSomethingWithSomeMap版本,它是脏的…你能发布SomeClass和SomeOtherClass签名吗?翻译成假名:-公共抽象类SomeClass-公共接口SomeOtherClass做简短的说明,SomeOtherClass是一个接口,它指定SomeClass要使用的键作为映射对象的标识符。密钥的类型因某个类的实现而异。@François使用给定的代码,以及您想要的方式;我认为不可能将此“错误”作为警告加以抑制。从我看来,我不能,因为“V扩展了SomeClass&SomeOtherClass”部分,因为这两个定义需要相互定义,我得到了一个关于“推断类型参数不符合边界”的错误。我建议您简化此方法。在两周内(最好是两个月),您将忘记所有类型参数的含义以及如何使用它。实际上,在它的上下文中,它更简单,它只验证您使用了正确类型的内容和正确类型的映射。我现在从基于反射的算法使用它的方式是一个例外情况。谢谢你的建议。是的,这正是问题所在。由于我在算法中使用反射,我可以假设我所做的是安全的,并添加所有必要的断言,但我无法说服编译器t
public abstract class SomeClass {    
  public abstract void method1();
}

public interface SomeOtherClass<K> {
  void method2(K value);
}

public class MyClass extends SomeClass implements SomeOtherClass<Integer> {
  @Override
  public void method1() {
    System.out.println("MyClass.method1");
  }

  @Override
  public void method2(Integer value) {
    System.out.println("MyClass.method2(" + value + ")");
  }
}

public class Indirection<K> extends SomeClass implements SomeOtherClass<K> {
  private final Object objectValue;

  public Indirection(final Object value) {
    this.objectValue = value;
  }

  @Override
  public void method1() {
    ((SomeClass) objectValue).method1();
  }

  @Override
  public void method2(K value) {
    @SuppressWarnings("unchecked")
    SomeOtherClass<K> delegate = ((SomeOtherClass<K>) objectValue);

    delegate.method2(value);
  }
}

public static void main(String[] args) {
  Map someMap = new HashMap<Integer, MyClass>();
  SomeClass someData = new MyClass();
  Indirection a = new Indirection(someData);
  doSomethingWithSomeMap(someMap, a, 12);
}

public static <K,V extends SomeClass & SomeOtherClass<K>>
void doSomethingWithSomeMap (Map<K,V> map, V data, K value) {
  data.method1();
  data.method2(value);
}
public <X extends SomeClass & SomeOtherClass>
void doReflectionMagic() {
    Map someMap = ...;
    X someData = (X) ...;
    doSomethingWithSomeMap(someMap, someData);
}