Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何确定泛型中的参数类型是否正确_Java_Generics_Casting_Map_Error Handling - Fatal编程技术网

Java 如何确定泛型中的参数类型是否正确

Java 如何确定泛型中的参数类型是否正确,java,generics,casting,map,error-handling,Java,Generics,Casting,Map,Error Handling,我正在编写一个带有以下必需方法签名的映射实现 我需要确保值的类型正确。我认为如果两种类型不相等,该检查将导致异常,但事实并非如此。还有什么可以检查的吗 public boolean containsValue(Object value) { try { V temp = (V) value; } catch (Exception e) { throw new ClassCastException("Value is not of correct

我正在编写一个带有以下必需方法签名的映射实现

我需要确保值的类型正确。我认为如果两种类型不相等,该检查将导致异常,但事实并非如此。还有什么可以检查的吗

public boolean containsValue(Object value) {

    try {
        V temp = (V) value;
    } catch (Exception e) {
        throw new ClassCastException("Value is not of correct type");
    }
    ...

它不抛出异常的原因是映射不能包含其他类型的对象,因此正确答案为false


至于您的问题,由于类型擦除,无法查看传递的对象是否与泛型类型相同。

由于类型擦除,您无法使用标准的
instanceof
运算符。规范方法是将类本身或其实例传递到某个地方

然后可以使用反射检查实例类型:

private Class<V> clazz; // somehow this gets set

public boolean containsValue(Object value){

    if(clazz.isInstance(value)){
        // safe:
        V temp = (V) value;
    }
注意:这保证了这是类型安全强制转换,但不要求类型相同,例如,
V
可以是
Number
,但
value
可以是
Integer
类型

只要获得
clazz
,您就可以在构造函数中强制执行它:

public class MyMap<K,V>{

    private final Class<V> clazz;

    public MyMap(Class<V> clazz){
        this.clazz = clazz;
    }

...
公共类MyMap{
私人期末班;
公共MyMap(类clazz){
this.clazz=clazz;
}
...
类的初始值设定项可能类似于:

 MyMap<Integer,String> foo = new MyMap<Integer,String>(String.class);
MyMap foo=newmymap(String.class);

对于这类事情,我通常赞成在构造函数中传递类型,并将字段标记为
final
,因为语义和限制会阻止您更改该字段,这是合理的,因为实例通常依赖于编译时保证,假定类型参数不变

为什么需要V类型的值?映射接口是这样定义的,不是偶然的

您应该接受作为对象的值,然后调用value.equals(地图中的其他值)

例如:

public boolean containsValue(Object value) {
    V v1 = ...;
    V v2 = ...;
    V v3 = ...;
    return value.equals(v1) || value.equals(v2) || value.equals(v3);
}
假设地图中有三个值v1、v2、v3。
v1、v2、v3的类型和参数值无关紧要,因为equals方法是在Object中定义的,您可以随时调用它来比较对象。如果值的类型确实不同,无法与V实例进行比较,那么它的equals方法将抛出ClassCastException,除非您捕获它,否则它将被传播r.别担心。

好吧,我有点明白你的意思,但是我该如何以及在哪里放置clazz呢?@Jeff:它只需要是类中的一个字段。我建议在构造函数中设置它的值。所以,它看起来像这样:public class MyMap{public MyMap(class clazz){this.clazz=clazz;}是它自己的独立构造函数吗?它如何与我已经编写的构造函数集成?@Jeff:你需要修改你当前的构造函数。编译器会对该泛型强制转换发出警告。不要忽略这些警告。如果要求它为V型,你就违反了
containsValue()的约定
方法,当
value.equals(v)
的映射中存在值
v
时,该方法返回true(或者如果它们都为null),无论
value
+1的类别如何,人们总是试图强制对象成为值的类型,这与Map中方法的规范相矛盾
value
是传入的外部对象,而不是Map中的对象
public boolean containsValue(Object value) {
    V v1 = ...;
    V v2 = ...;
    V v3 = ...;
    return value.equals(v1) || value.equals(v2) || value.equals(v3);
}