Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.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 如何使用2种不同类型的哈希映射定义2个构造函数?_Java_Constructor_Hashmap_Polymorphism - Fatal编程技术网

Java 如何使用2种不同类型的哈希映射定义2个构造函数?

Java 如何使用2种不同类型的哈希映射定义2个构造函数?,java,constructor,hashmap,polymorphism,Java,Constructor,Hashmap,Polymorphism,我有一个包含2个HashMap字段的类,如下所示- HashMap<String, Integer> map1; HashMap<String, String> map2; HashMap-map1; HashMap-map2; 现在,我只想传递构造函数中的一个映射,即map1或map2类型。但是,我不能用不同类型的哈希映射定义两个不同的构造函数。这是一个解决办法吗 您不能:泛型在编译阶段被剥离:编译后的代码在这两种情况下都只看到HashMap 此过程的技术名称为类型

我有一个包含2个HashMap字段的类,如下所示-

HashMap<String, Integer> map1;
HashMap<String, String> map2;
HashMap-map1;
HashMap-map2;

现在,我只想传递构造函数中的一个映射,即map1或map2类型。但是,我不能用不同类型的哈希映射定义两个不同的构造函数。这是一个解决办法吗

您不能:泛型在编译阶段被剥离:编译后的代码在这两种情况下都只看到
HashMap

此过程的技术名称为类型擦除。看

在很多方面都使java泛型不如C++模板。

有几个选项:

1) 一个构造函数,它接受两个映射,并且在传递null时是安全的

public MyClass( Map<String, Integer> map1, Map<String, String> map2 ) {
    if ( map1 != null ) { this.map1 = map1; }
    if ( map2 != null ) { this.map2 = map2; }
}
publicmyclass(地图map1、地图map2){
如果(map1!=null){this.map1=map1;}
如果(map2!=null){this.map2=map2;}
}
2) 每个地图的设置器

public MyClass {
    private Map<String, Integer> map1;
    private Map<String, String> map2;
    public void setMap1( Map<String, Integer> map1 ) {
        this.map1 = map1;
    }
    public void setMap2( Map<String, String> map2 ) {
        this.map2 = map2;
    }
}
公共MyClass{
私人地图map1;
私有地图map2;
公共void setMap1(映射map1){
this.map1=map1;
}
公共void setMap2(映射map2){
this.map2=map2;
}
}
3) 一个生成器,允许您区分贴图并正确构造对象(调用setter)

公共MyClass{
私人地图map1;
私有地图map2;
//假装你不想让人们在施工后交换地图,这样你就可以保护这里的设定者。
受保护的无效集合映射1(映射映射1){
this.map1=map1;
}
受保护的无效集合映射1(映射映射2){
this.map2=map2;
}
//映射和其他属性的getter
公共静态生成器(){
返回新的生成器();
}
公共静态类生成器{
私人地图map1;
私有地图map2;
公共生成器withMap1(地图){
map1=map;
归还这个;
}
公共生成器withMap2(地图地图){
map2=map;
归还这个;
}
公共MyClass构建(){
MyClass c=新的MyClass();
//可能是检查映射的特定值或有效性的条件代码
c、 setMap1(map1);
c、 setMap2(map2);
//其他字段的初始化
返回c;
}
}
公共静态void main(字符串[]args){
//样本使用
MyClass instance1=MyClass.builder().withMap1(myMap1.build();
MyClass instance2=MyClass.builder().withMap2(myMap2.build();
MyClass instance3=MyClass.builder().withMap1(myMap1).withMap2(myMap2.build();
}
}
4) 静态工厂(如下面Evgeniy Dorofev所指出)

公共MyClass{
私人地图map1;
私有地图map2;
//其他属性
私有MyClass(){}
公共静态MyClass withMap1(Map-Map){
MyClass c=新的MyClass();
c、 map1=map;
返回c;
}
公共静态MyClass withMap2(Map-Map){
MyClass c=新的MyClass();
c、 map2=map;
返回c;
}
//接球手和接球手
}

作为一种解决方法,您可以使用具有不同名称的静态工厂方法

public class MyObject<T> {
    public MyObject(Map<String, T> map) {
         // process map
    }
}

但是,您将无法在运行时确定T的具体类型…

HashMap map1和HashMap map2完全不同。它们不能互换。因此,您需要定义一个传递两个哈希映射的构造

  public MyClass(HashMap<String, Integer> map1, HashMap<String, String> map2){
        ............
  }
publicmyclass(HashMap-map1、HashMap-map2){
............
}

我同意。。。但对于作为第三个选项提供给您的变通方法的构建器模式,可以有一些改进。 Builder模式的一个主要优点是它从父类中消除了setter函数,客户机现在调用Builder类的setter类函数来设置父类的实例变量

public class MyClass{
    private Map<String, Integer> map1;
    private Map<String, String> map2;

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private Map<String, Integer> map1;
        private Map<String, String> map2;

        public Builder withMap1(Map<String, Integer> map) {
            map1 = map;
            return this;
        }

        public Builder withMap2(Map<String, String> map) {
            map2 = map;
            return this;
        }

        public MyClass build() {
            return new MyClass(this);
        }

    }

    public MyClass(Builder b) {
        map1 = b.map1;
        map2 = b.map2;
    }

    public static void main(String[] args) {
        // sample usage
        MyClass instance1 = MyClass.builder().withMap1(myMap1).build();
        MyClass instance2 = MyClass.builder().withMap2(myMap2).build();
        MyClass instance3 = MyClass.builder().withMap1(myMap1).withMap2(myMap2).build();
    }
}
公共类MyClass{
私人地图map1;
私有地图map2;
公共静态生成器(){
返回新的生成器();
}
公共静态类生成器{
私人地图map1;
私有地图map2;
公共生成器withMap1(地图){
map1=map;
归还这个;
}
公共生成器withMap2(地图地图){
map2=map;
归还这个;
}
公共MyClass构建(){
返回新的MyClass(此);
}
}
公共MyClass(生成器b){
map1=b.map1;
map2=b.map2;
}
公共静态void main(字符串[]args){
//样本使用
MyClass instance1=MyClass.builder().withMap1(myMap1.build();
MyClass instance2=MyClass.builder().withMap2(myMap2.build();
MyClass instance3=MyClass.builder().withMap1(myMap1).withMap2(myMap2.build();
}
}

回答得很好。它提供了解决问题的方法+1我不明白为什么在第一个解决方案中检查
null
。AFAIK赋值
null
不应该产生任何错误,在代码
中的这一点上,mapX
null
s,这意味着赋值
null
不会改变任何事情。我可以理解,如果有一个
else
mapX
属性初始化为一个新的空哈希映射,但是现在看来那些
if
似乎毫无用处。或者我错了?在这种情况下,是的,空检查是多余的,但我把它放在那里只是为了证明他们可以做任何他们想做的事情。也许在声明时(代码示例中没有显示),他们正在将map1和map2初始化为空hashmap,这样就不必在其他地方执行空检查。然后,空检查在构造函数中是有意义的,这样就不会覆盖默认值。我认为您在示例4中的方法
withMap1
withMap2
中错过了返回类型
MyClass
。第二个选项似乎不起作用,错误是
方法xxx(Map)的擦除是错误的
new MyObject<Integer>(map1);
new MyObject<String>(map2);
public class MyObject {
    public <T> MyObject(Map<String, T> map) {
        // process map
    }
}
new MyObject(map1);
new MyObject(map2);
  public MyClass(HashMap<String, Integer> map1, HashMap<String, String> map2){
        ............
  }
public class MyClass{
    private Map<String, Integer> map1;
    private Map<String, String> map2;

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private Map<String, Integer> map1;
        private Map<String, String> map2;

        public Builder withMap1(Map<String, Integer> map) {
            map1 = map;
            return this;
        }

        public Builder withMap2(Map<String, String> map) {
            map2 = map;
            return this;
        }

        public MyClass build() {
            return new MyClass(this);
        }

    }

    public MyClass(Builder b) {
        map1 = b.map1;
        map2 = b.map2;
    }

    public static void main(String[] args) {
        // sample usage
        MyClass instance1 = MyClass.builder().withMap1(myMap1).build();
        MyClass instance2 = MyClass.builder().withMap2(myMap2).build();
        MyClass instance3 = MyClass.builder().withMap1(myMap1).withMap2(myMap2).build();
    }
}