是否可以创建适用于Java中不同类的泛型方法?

时间:2018-03-27 18:03:26

标签: java generics java-8 code-reuse

我有不同的类,其结构如下:

public class MyClass {
    private String name;
    private List<International> internationalList;
}

我想要的是拥有一个给定本地化的通用方法(例如:“en-us”),它在internationalList中搜索并使用正确的语言设置名称。

示例:

 public MyClass myMethod(String local, MyClass object){

            for (International international : object.internationalList){
                if(local.equals(international.language)){
               object.name = international.translation
         }
      }
    return myObject;
 }

我不想将此代码重写到每个类。是否可以创建适用于具有此结构的所有类的泛型方法?

5 个答案:

答案 0 :(得分:1)

定义界面

您可以创建一个由MyClass

实施的界面
public interface LocationAware {
    String getName();
    void setName(String name);
    List<International> getInternationals();
    void setInternationals(List<International> internationals);
}

然后实现像

这样的类
public static class MyClass implements LocationAware {
    private String name;
    private List<International> internationalList;
    // getter and setters
}

您还可以使用International的接口并实现该类。

public interface International {
    String getLanguage();
    String getTranslation();
}

使用辅助方法

你可以在任何你想要的类中使用泛型的辅助方法,例如: StaticClass

public static <T extends LocationAware> T changeLocationName(String local, T object) {
    for (International international : object.getInternationals()) {
        if(local.equals(international.getLanguage())) {
            object.setName(international.getTranslation());
        }
    }
    return object;
}

可以通过以下方式调用:

StaticClass.changeLocationName("en-us", myClass);

使用默认方法

由于您已经在使用接口,因此您可以使用默认方法,在没有辅助方法的情况下为您提供相同的功能。

public interface LocationAware {
    default void changeLocationName(String local) {
        for (International international : getInternationals()) {
            if(local.equals(international.getLanguage())) {
                setName(international.getTranslation());
            }
        }
    }
    String getName();
    void setName(String name);
    List<International> getInternationals();
    void setInternationals(List<International> internationals);
}

只需使用类方法:

MyClass myClass = new Myclass(); // create and add name and internationals
myClass.changeLocationName("en-us"); // then change the location

在这里,您可以决定如何处理local的许多其他方式,例如,您可以存储值,当您使用getName()时,会以dinamically的形式返回当前名称,因此您不能; t每次都改变当前名称,(也可以使用地图获得很小的性能提升)。

public interface LocationAware {
    default String getName() {
        return getInternationals().get(getLocal());
    }
    void setName(String local);
    String getLocal();
    void setLocal(String local);
    Map<String, International> getInternationals();
    void setInternationals(Map<String, International> internationals);
}

注意:您应该处理位置不存在的情况

答案 1 :(得分:0)

这是一个静态方法,可以在没有泛型的情况下解决问题。

public static String lookUpName(String locale, String List<International> list) {
  for (International international : list) {
    if (local.equals(international.language) {
      return international.translation;
    }
  }
  return null; //or “” if that is preferred 
}

答案 2 :(得分:0)

这可能更多地被视为评论,但我想添加一些不适合评论的详细信息。

不清楚哪个类包含myMethod(...),但该方法似乎支持来自包含数据的MyClass的国际化外部。这打破了告诉不要问的原则。

更多的OOP方法是让MyClass知道如何进行自己的翻译。例如:

public class NameTranslator {
   // constructor loads the List (or Map)

    public String translate(String locale, String name) {
       ...
    }
}

MyClass知道它的语言环境,并使用翻译器:

public class MyClass {
    private final NameTranslator translator;
    private final String locale;
    private String name;

    // constructor to set the translator and locale

    public void setName(String name) {
       String translatedName = translator.translate(locale, name);
       if (translatedName != null) {
         this.name = translatedName;
       } else {
         this.name = name;  // or throw an IllegalStateException?
       }
    }

    public String getName() {
      return name;
    }
}

因此,翻译人员不需要了解MyClass或任何其他类别的任何内容。

此外,在搜索要翻译的项目时,Map会比List快。

答案 3 :(得分:0)

定义一个像

这样的通用合约
public interface CommonInterface {
    String getName();
    void setName(String name);
    List<International> getInternational();
}

让所有类实现它。这是一个这样的课程。

public class MyClass implements CommonInterface {
    private String name;
    private List<International> internationalList;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
         this.name = name;
    }

    @Override
    public List<International> getInternational() {
        return internationalList; //Or create a defensive copy
    }
}

您的常用方法看起来像

public <T extends CommonInterface> T myMethod(String local, T myObject) {
    for (International international : myObject.getInternational()){
        if(local.equals(international.language)) { //Better to avoid direct access and include getters in International class
            myObject.setName(international.translation);
        }
    }
    return myObject;
}

答案 4 :(得分:0)

创建一个抽象类,将方法“MyMethod”标记为static,并以静态方式从您需要的类中调用它。一个简单的解决方案。