Java 如何使用2种不同类型的哈希映射定义2个构造函数?
我有一个包含2个HashMap字段的类,如下所示-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 此过程的技术名称为类型
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();
}
}