Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.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_Javafx - Fatal编程技术网

Java 无法在映射中设置泛型属性的值

Java 无法在映射中设置泛型属性的值,java,javafx,Java,Javafx,我试图在映射中设置属性的值,但出现以下错误: The method setValue(capture#7-of ?) in the type WritableValue<capture#7-of ?> is not applicable for the arguments (capture#8-of ?) 我可以在没有地图的情况下进一步简化: Property<?> p1 = new SimpleIntegerProperty(5); Property<?>

我试图在映射中设置属性的值,但出现以下错误:

The method setValue(capture#7-of ?) in the type WritableValue<capture#7-of ?> is not applicable for the arguments (capture#8-of ?)
我可以在没有地图的情况下进一步简化:

Property<?> p1 = new SimpleIntegerProperty(5);
Property<?> p2 = new SimpleIntegerProperty(10);
p1.setValue(p2.getValue());//Same (basic) error
p1.setValue(new Object());//Same (basic) error
Property p1=新的SimpleIntegerProperty(5);
属性p2=新的SimpleIntegerProperty(10);
p1.setValue(p2.getValue())//相同(基本)错误
p1.设置值(新对象())//相同(基本)错误

我正在使用Java 1.8 JDK

如果您希望继续使用以下类型,请尝试以下操作:

        IntegerProperty p1 = new SimpleIntegerProperty(5);
        IntegerProperty p2 = new SimpleIntegerProperty(10);
        p1.setValue(p2.getValue());
或该类型没有安全性:

        Property p1 = new SimpleIntegerProperty(5);
        Property p2 = new SimpleIntegerProperty(10);
        p1.setValue(p2.getValue());

一,。E删除通配符。

这不是JavaFX问题,这是泛型问题。一旦有了通配符类型,
setValue
方法就有了类型
T
。。。您还没有指定。换句话说,这是不好的:

Property<?> p1 = new SimpleIntegerProperty(5);
Property<?> p2 = new SimpleIntegerProperty(10);
p1.setValue(p2.getValue());

使
Property
成为一个接口,并具有
SimpleIntegerProperty
SimpleStringProperty
实现
Property
。然后您将有一个
HashMap

问题是您尝试执行的操作本质上是不安全的。从编程逻辑中,您可能知道与
map1
中的
“key1”
关联的属性类型与
map2
中的
“key1”
关联的属性类型相同,但编译器不可能保证这一事实。因此,对于当前的结构,您唯一的选择就是放弃编译时安全性

这里的根本问题是
Map
为您的需求提供了错误的API(即使它的基本功能是您所需要的)
Map
是一个同质容器,这意味着给定Map中的所有值都是同一类型的。这是由API强制执行的:
public V get(K键)和<代码>公开作废(K键,V值)始终使用相同的类型
V
,这对于任何单个
Map
实例都是固定的。您真正想要的是一个异构容器,其中的值根据键的不同而变化。因此,您需要一个API,其中容器实例的
V
不是固定的,而是根据键的值对方法
get
put
的每次调用进行更改。因此,您需要一些
get
put
方法是通用方法的东西:

public interface Container<K> { // K is the type of the key...

    public <V> V get(K key) ;
    public <V> void put(K key, V value);

}
现在定义一个容器类作为映射。这里的基本思想是有两种方法:

public <T> void put(TypedKey<T, K> key, Property<T> property)

public <T> Property<T> get(TypedKey<T, K> key)
请注意,很难将其变成
ObservableMap
,原因与引言中概述的相同:
ObservableMap
接口定义了同质方法(实际上是从
Map
接口继承的),而您无法以满足需求的方式实现这些方法。但是,您可以轻松地使此实现
javafx.beans.Observable
,这将允许您使用它注册
invalizationlistener
s,并在绑定中使用它:

   public class TypedPropertyMap<K> implements Observable { 
        private final ObservableMap<TypedKey<?, K>, Property<?>> map = FXCollections.observableHashMap();

        @Override
        public void addListener(InvalidationListener listener) {
            map.addListener(listener);
        }

        @Override
        public void removeListener(InvalidationListener listener) {
            map.removeListener(listener);
        }

        // remaining code as before...
    }
公共类TypedPropertyMap实现了可观察的{
私有最终ObservaleMap>map=FXCollections.Observalehashmap();
@凌驾
public void addListener(invalizationListener侦听器){
addListener(监听器);
}
@凌驾
公共void RemovelListener(InvalizationListener侦听器){
map.removeListener(监听器);
}
//剩下的代码和以前一样。。。
}

您使用的是什么版本的Java?您试图实现什么样的功能?你为什么混血?地图的数据来自哪里?我需要能够在地图中包含多个属性类型。不幸的是,这在我的情况下不起作用。然后Eclipse黄色在它下面加下划线,说我需要一个类型。我知道我可以做@SuppressWarnings,但我希望有更好的方法,我从来没有使用过这些,现在不想开始。你在没有类型安全的情况下工作,你期望什么?这是我不想做的,我希望它是类型安全的。然后你需要指定一个类型。地图的键是什么类型的,值是什么类型的?您不能像示例中那样混合整数和字符串,并且必须是类型安全的。这是不可能的。我不确定这是否有效,因为
Property
SimpleIntegerProperty
SimpleStringProperty
都是内置类。哦,我以前没有使用过JavaFX,所以我没有意识到。然后,要么使用一个
HashMap
并使用强制类型转换,要么使用单独的
HashMap
s。我还必须指出,我正在使用JavaFX的
FXCollections
生成我的一个映射,所以我认为我无法生成
TypedPropertyMap
。也许在声明
observeMap
时,我仍然可以使用
TypedKey
而不是
String
?我需要考虑一下。制作
TypedPropertyMap
实现
javafx.beans.Observable
,非常容易,但是我看不出有什么办法可以让它实现
javafx.collections.ObservableMap
。你的实际需求是什么?如果它实现了
Observable
并另外定义了
addListener(mapchangeStener)
removeListener(mapchangeStener)
方法,但没有实现
ObservableMap
,那会起作用吗?即使这样,您也可能无法在
Change
事件上获得完整的类型安全性。我不知道为什么要使用
FXCollections
。我不认为它被用在任何视图或任何东西中。我想我可以在这种情况下使用
TypedPropertyMap
。我想问题是:您是将侦听器附加到它还是绑定到它,代码中的任何位置?查看我的代码,我想我不需要侦听
映射中的更改,只需侦听
映射中的
属性。我想
TypedPropertyMap
可以正常工作。
TypedPropertyMap
是否应包含内部
Map
或扩展
Map
?沃
Property<?> mapProperty = map2.get("key1");
if(mapProperty instanceof IntegerProperty) { 
   ((IntegerProperty) mapProperty).setValue((Integer) map1.get("key1").getValue());
} else {
   // handle the error
}
public interface Container<K> { // K is the type of the key...

    public <V> V get(K key) ;
    public <V> void put(K key, V value);

}
    /**
     * @param <T> The type associated with this key
     * @param <K> The actual type of the key itself
     */
    public class TypedKey<T, K> {
        private final Class<T> type ;
        private final K key ;

        public TypedKey(Class<T> type, K key) {
            if (type == null || key == null) {
                throw new NullPointerException("type and key must be non-null");
            }
            this.type = type ;
            this.key = key ;
        }

        @Override
        public boolean equals(Object o) {
            if (o == null) return false ;
            if (! (o instanceof TypedKey)) {
                return false ;
            }
            TypedKey<?, ?> other = (TypedKey<?, ?>) o ;
            return other.type.equals(type) && other.key.equals(key);
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, key);
        }
    }
// String key to map to Property<Number>:
TypedKey<Number, String> key1 = new TypedKey<>(Number.class, "key1");

// String key to map to Property<String>:
TypedKey<String, String> key2 = new TypedKey<>(String.class, "key2");
public <T> void put(TypedKey<T, K> key, Property<T> property)

public <T> Property<T> get(TypedKey<T, K> key)
    /**
     * @param <K> The type of the key in the TypedKey
     */
    public class TypedPropertyMap<K> { 
        private final Map<TypedKey<?, K>, Property<?>> map = new HashMap<>();

        public <T> void put(TypedKey<T, K> key, Property<T> property) {
            map.put(key, property);
        }

        @SuppressWarnings("unchecked")
        public <T> Property<T> get(TypedKey<T, K> key) {

            // by virtue of the API we defined, the property associated with
            // key must be a Property<T> (even though the underlying map does not know it):

            return (Property<T>) map.get(key);
        }
    }
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import javafx.beans.property.Property;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;


public class TypedPropertyMapTest {

    public static void main(String[] args) {
        TypedPropertyMap<String> map1 = new TypedPropertyMap<>();
        TypedPropertyMap<String> map2 = new TypedPropertyMap<>();

        TypedKey<Number, String> key1 = new TypedKey<>(Number.class, "key1");
        TypedKey<String, String> key2 = new TypedKey<>(String.class, "key2");

        map1.put(key1, new SimpleIntegerProperty(5));
        map1.put(key2, new SimpleStringProperty("hi"));

        map2.put(key1, new SimpleIntegerProperty());
        map2.put(key2, new SimpleStringProperty());

        map2.get(key1).setValue(map1.get(key1).getValue());
        map2.get(key2).setValue(map1.get(key2).getValue());

        System.out.println(map2.get(key1).getValue());
        System.out.println(map2.get(key2).getValue());

    }


    /**
     * @param <T> The type associated with this key
     * @param <K> The actual type of the key itself
     */
    public static class TypedKey<T, K> {
        private final Class<T> type ;
        private final K key ;

        public TypedKey(Class<T> type, K key) {
            if (type == null || key == null) {
                throw new NullPointerException("type and key must be non-null");
            }
            this.type = type ;
            this.key = key ;
        }

        @Override
        public boolean equals(Object o) {
            if (o == null) return false ;
            if (! (o instanceof TypedKey)) {
                return false ;
            }
            TypedKey<?, ?> other = (TypedKey<?, ?>) o ;
            return other.type.equals(type) && other.key.equals(key);
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, key);
        }
    }

    /**
     * @param <K> The type of the key in the TypedKey
     */
    public static class TypedPropertyMap<K> { 
        private final Map<TypedKey<?, K>, Property<?>> map = new HashMap<>();

        public <T> void put(TypedKey<T, K> key, Property<T> property) {
            map.put(key, property);
        }

        @SuppressWarnings("unchecked")
        public <T> Property<T> get(TypedKey<T, K> key) {

            // by virtue of the API we defined, the property associated with
            // key must be a Property<T> (even though the underlying map does not know it):

            return (Property<T>) map.get(key);
        }
    }
}
   public class TypedPropertyMap<K> implements Observable { 
        private final ObservableMap<TypedKey<?, K>, Property<?>> map = FXCollections.observableHashMap();

        @Override
        public void addListener(InvalidationListener listener) {
            map.addListener(listener);
        }

        @Override
        public void removeListener(InvalidationListener listener) {
            map.removeListener(listener);
        }

        // remaining code as before...
    }