如何调用一个名为java中字符串变量值的方法?

时间:2022-02-28 11:44:34

This is the code of the method that I want to simplify. The method name I call of SerializedExpFamMixture class is exactly the value of "model", my question is how to assign the value of "model" directly as the name of the method instead of using "if" to determine which method I should call. Since by using "if", I need to list all the possible values of "model" and judge which method I should use.

这是我想要简化的方法的代码。我调用SerializedExpFamMixture类的方法名称正是“模型”的值,我的问题是如何直接将“model”的值分配为方法的名称,而不是使用“if”来确定我应该调用哪个方法。由于使用“if”,我需要列出“模型”的所有可能值,并判断我应该使用哪种方法。

Thank you very much for help. I am new to java.

非常感谢您的帮助。我是java的新手。

public static SerializedExpFamMixture RateMtxModel(String model)
 {
   SerializedExpFamMixture result=new SerializedExpFamMixture();
   if(model=="kimura1980()")
     result=SerializedExpFamMixture.kimura1980();
   if(model=="accordance()")
     result=SerializedExpFamMixture.accordance();
   if(model=="pair()")
     result=SerializedExpFamMixture.pair();
   return result;

 } 

3 个解决方案

#1


0  

Since you are new to Java, it's time for some general pointers:

由于您不熟悉Java,现在是时候提出一些一般性的指示:

  1. In Java, we usually name our methods with camelCase, so the first letter is lower case.
  2. 在Java中,我们通常使用camelCase命名我们的方法,因此第一个字母是小写。

  3. Also, in Java we usually leave the opening curly-bracket on the same line as the code (no newline).
  4. 此外,在Java中,我们通常将开始的花括号放在与代码相同的行上(没有换行符)。

  5. Always use final on your variables. At least your parameters. That way you won't overwrite it, and thus won't have to try to figure out which value it actually has at runtime.
  6. 始终对变量使用final。至少你的参数。这样你就不会覆盖它,因此不必试图找出它在运行时实际具有的值。

  7. Use curly-brackets! Please!
  8. 使用大括号!请!

  9. The result variable is not actually needed.
  10. 实际上并不需要结果变量。

  11. Use the equals-method to compare Strings.
  12. 使用equals-method比较字符串。

  13. If you only want one result, use else-if
  14. 如果您只想要一个结果,请使用else-if

Fixing these things, your method looks like this:

修复这些问题,您的方法如下所示:

public static SerializedExpFamMixture rateMtxModel(String model) {
   if (model.equals("kimura1980()")) {
     return SerializedExpFamMixture.kimura1980();
   } else if (model.equals("accordance()")) {
     return SerializedExpFamMixture.accordance();
   } else if(model.equals("pair()")) {
     return SerializedExpFamMixture.pair();
   } 
   return new SerializedExpFamMixture();
}  

Next, let's look at what you are actually trying to do here. You want to pass some Strings around, and use them as a basis for creating objects. And now, with the advice given here, you will do this using reflection. This does not sound like a very good idea to me. Say you were to go through with this, and this happened:

接下来,让我们来看看你在这里尝试做什么。您想要传递一些字符串,并将它们用作创建对象的基础。现在,根据这里给出的建议,你将使用反射来做到这一点。这对我来说听起来不是一个好主意。说你要经历这个,这发生了:

rateMtxModel("kinura1980");

Small typo, hard to spot, will give unexpected results. If you were actually calling a method the compiler would let you know that you messed up, now you will get no warning (btw did you see both errors in that method call?). The same if someone were to delete the accordance()-method, the compiler would not alert them that this will break the program.

难以发现的小错字会带来意想不到的结果。如果你实际上正在调用一个方法,编译器会让你知道你搞砸了,现在你不会得到任何警告(顺便说一下,你在这个方法调用中看到了两个错误吗?)。如果有人要删除() - 方法,编译器也不会提醒他们这会破坏程序。

If it was up to be I would just use the static factory-methods in SerializedExpFamMixture directly, but if you have to do it like this (if the task at hand is using a String input to create an object) I would do something like this:

如果它是我将直接使用SerializedExpFamMixture中的静态工厂方法,但如果你必须这样做(如果手头的任务是使用String输入来创建一个对象)我会做这样的事情:

public enum Something {
    KIMURA1980("kimura1980()"),
    ACCORDANCE("accordance()"),
    PAIR("pair()");

    private final String stringValue;

    private Something(final String stringValue) {
        this.stringValue = stringValue;
    }

    public static Something fromString(final String string) {
        for (final Something something : values()) {
            if (something.stringValue.equals(string)) {
                return something;
            }
        }
        return null;
    }
}

public static SerializedExpFamMixture rateMtxModel(final String model) {
   if (model == null) {
       throw new IllegalArgumentException("model is null!");
   }

   final Something something = Something.fromString(model);

   if (something == null) {
      return new SerializedExpFamMixture();
   }

   switch(something) {
       case KIMURA1980:
           return SerializedExpFamMixture.kimura1980();
       case ACCORDANCE:
           return SerializedExpFamMixture.accordance();
       case PAIR:
           return SerializedExpFamMixture.pair();
       default:
           return new SerializedExpFamMixture();    
   }   
}  

This way, the one place where you will use the Strings is in the enum, the rest of the code will use the enum constants and thus have the safety of the compiler to rely on.

这样,您将使用字符串的一个位置在枚举中,其余代码将使用枚举常量,因此具有编译器依赖的安全性。

One could also leave the linking between operation and String to the enum, like this:

也可以将操作和String之间的链接留给枚举,如下所示:

interface Operation<T> {
    public T run(); 
}

public enum Something {
    KIMURA1980("kimura1980()", new Operation<SerializedExpFamMixture>() {
                                      public SerializedExpFamMixture run() { 
                                          return SerializedExpFamMixture.kimura1980();
                                      } 
                               }) ,
    ACCORDANCE("accordance()", new Operation<SerializedExpFamMixture>() {
                                       public SerializedExpFamMixture run() { 
                                           return SerializedExpFamMixture.accordance();
                                       } 
                               }),
    PAIR("pair()", new Operation<SerializedExpFamMixture>() {
                           public SerializedExpFamMixture run() { 
                               return SerializedExpFamMixture.pair();
                           } 
                   }),
    DEFAULT(null, new Operation<SerializedExpFamMixture>() {
                          public SerializedExpFamMixture run() { 
                              return new SerializedExpFamMixture();
                          } 
                  });

    private final String stringValue;
    private final Operation<SerializedExpFamMixture> operation;

    private Something(final String stringValue, final Operation<SerializedExpFamMixture> operation) {
        this.stringValue = stringValue;
        this.operation = operation;
    }

    public static Something fromString(final String string) {
        if (string != null) {
            for (final Something something : values()) {
                if (string.equals(something.stringValue)) {
                    return something;
                }
            }
        }
        return DEFAULT;
    }

    public SerializedExpFamMixture getCorrespondingSerializedExpFamMixture() {
        return operation.run();
    }
}

With this setup in the enum (I think the Operation-part can be trimmed out with Java8), the method will be as simple as:

在枚举中使用此设置(我认为可以使用Java8修剪操作部分),该方法将如下所示:

public static SerializedExpFamMixture rateMtxModel(String model) {
    return Something.fromString(model).getCorrespondingSerializedExpFamMixture();
}

#2


2  

One way you can approach this is to use Reflection:

您可以采用的一种方法是使用Reflection:

Method method = myClass.getClass().getMethod("doSomething", null);
method.invoke(myClass, null);

#3


0  

Use reflection, but you need to consider a few things:

使用反射,但您需要考虑以下几点:

  1. Bug alert! Comparing Strings using == doesn't work as expected in java - use .equals() instead. However, the solution below bypasses that problem
  2. 错误提醒!使用==比较字符串在java中无法正常工作 - 请改用.equals()。但是,下面的解决方案绕过了这个问题

  3. For the general case, which includes methods not visible to the invoker, you need to consider accessibility, both in finding the method and invoking it
  4. 对于包含调用者不可见的方法的一般情况,您需要考虑可访问性,包括查找方法和调用方法

  5. You don't need the result variable, and even if using your code, don't need to initialize it
  6. 您不需要结果变量,即使使用您的代码,也不需要初始化它

Try this:

String methodName = model.replace("(", "").replace(")", "");
try {
    // getMethod() returns only public methods, getDeclaredMethod() returns any visibility
    Method method = SerializedExpFamMixture.class.getDeclaredMethod(methodName);
    // if the method is not guaranteed to be visible (eg public) you need this:
    method.setAccessible(true);
    return (SerializedExpFamMixture) method.invoke(null); // how to invoke on the class object
} catch (Exception forBrevity) {
    return new SerializedExpFamMixture();
}

#1


0  

Since you are new to Java, it's time for some general pointers:

由于您不熟悉Java,现在是时候提出一些一般性的指示:

  1. In Java, we usually name our methods with camelCase, so the first letter is lower case.
  2. 在Java中,我们通常使用camelCase命名我们的方法,因此第一个字母是小写。

  3. Also, in Java we usually leave the opening curly-bracket on the same line as the code (no newline).
  4. 此外,在Java中,我们通常将开始的花括号放在与代码相同的行上(没有换行符)。

  5. Always use final on your variables. At least your parameters. That way you won't overwrite it, and thus won't have to try to figure out which value it actually has at runtime.
  6. 始终对变量使用final。至少你的参数。这样你就不会覆盖它,因此不必试图找出它在运行时实际具有的值。

  7. Use curly-brackets! Please!
  8. 使用大括号!请!

  9. The result variable is not actually needed.
  10. 实际上并不需要结果变量。

  11. Use the equals-method to compare Strings.
  12. 使用equals-method比较字符串。

  13. If you only want one result, use else-if
  14. 如果您只想要一个结果,请使用else-if

Fixing these things, your method looks like this:

修复这些问题,您的方法如下所示:

public static SerializedExpFamMixture rateMtxModel(String model) {
   if (model.equals("kimura1980()")) {
     return SerializedExpFamMixture.kimura1980();
   } else if (model.equals("accordance()")) {
     return SerializedExpFamMixture.accordance();
   } else if(model.equals("pair()")) {
     return SerializedExpFamMixture.pair();
   } 
   return new SerializedExpFamMixture();
}  

Next, let's look at what you are actually trying to do here. You want to pass some Strings around, and use them as a basis for creating objects. And now, with the advice given here, you will do this using reflection. This does not sound like a very good idea to me. Say you were to go through with this, and this happened:

接下来,让我们来看看你在这里尝试做什么。您想要传递一些字符串,并将它们用作创建对象的基础。现在,根据这里给出的建议,你将使用反射来做到这一点。这对我来说听起来不是一个好主意。说你要经历这个,这发生了:

rateMtxModel("kinura1980");

Small typo, hard to spot, will give unexpected results. If you were actually calling a method the compiler would let you know that you messed up, now you will get no warning (btw did you see both errors in that method call?). The same if someone were to delete the accordance()-method, the compiler would not alert them that this will break the program.

难以发现的小错字会带来意想不到的结果。如果你实际上正在调用一个方法,编译器会让你知道你搞砸了,现在你不会得到任何警告(顺便说一下,你在这个方法调用中看到了两个错误吗?)。如果有人要删除() - 方法,编译器也不会提醒他们这会破坏程序。

If it was up to be I would just use the static factory-methods in SerializedExpFamMixture directly, but if you have to do it like this (if the task at hand is using a String input to create an object) I would do something like this:

如果它是我将直接使用SerializedExpFamMixture中的静态工厂方法,但如果你必须这样做(如果手头的任务是使用String输入来创建一个对象)我会做这样的事情:

public enum Something {
    KIMURA1980("kimura1980()"),
    ACCORDANCE("accordance()"),
    PAIR("pair()");

    private final String stringValue;

    private Something(final String stringValue) {
        this.stringValue = stringValue;
    }

    public static Something fromString(final String string) {
        for (final Something something : values()) {
            if (something.stringValue.equals(string)) {
                return something;
            }
        }
        return null;
    }
}

public static SerializedExpFamMixture rateMtxModel(final String model) {
   if (model == null) {
       throw new IllegalArgumentException("model is null!");
   }

   final Something something = Something.fromString(model);

   if (something == null) {
      return new SerializedExpFamMixture();
   }

   switch(something) {
       case KIMURA1980:
           return SerializedExpFamMixture.kimura1980();
       case ACCORDANCE:
           return SerializedExpFamMixture.accordance();
       case PAIR:
           return SerializedExpFamMixture.pair();
       default:
           return new SerializedExpFamMixture();    
   }   
}  

This way, the one place where you will use the Strings is in the enum, the rest of the code will use the enum constants and thus have the safety of the compiler to rely on.

这样,您将使用字符串的一个位置在枚举中,其余代码将使用枚举常量,因此具有编译器依赖的安全性。

One could also leave the linking between operation and String to the enum, like this:

也可以将操作和String之间的链接留给枚举,如下所示:

interface Operation<T> {
    public T run(); 
}

public enum Something {
    KIMURA1980("kimura1980()", new Operation<SerializedExpFamMixture>() {
                                      public SerializedExpFamMixture run() { 
                                          return SerializedExpFamMixture.kimura1980();
                                      } 
                               }) ,
    ACCORDANCE("accordance()", new Operation<SerializedExpFamMixture>() {
                                       public SerializedExpFamMixture run() { 
                                           return SerializedExpFamMixture.accordance();
                                       } 
                               }),
    PAIR("pair()", new Operation<SerializedExpFamMixture>() {
                           public SerializedExpFamMixture run() { 
                               return SerializedExpFamMixture.pair();
                           } 
                   }),
    DEFAULT(null, new Operation<SerializedExpFamMixture>() {
                          public SerializedExpFamMixture run() { 
                              return new SerializedExpFamMixture();
                          } 
                  });

    private final String stringValue;
    private final Operation<SerializedExpFamMixture> operation;

    private Something(final String stringValue, final Operation<SerializedExpFamMixture> operation) {
        this.stringValue = stringValue;
        this.operation = operation;
    }

    public static Something fromString(final String string) {
        if (string != null) {
            for (final Something something : values()) {
                if (string.equals(something.stringValue)) {
                    return something;
                }
            }
        }
        return DEFAULT;
    }

    public SerializedExpFamMixture getCorrespondingSerializedExpFamMixture() {
        return operation.run();
    }
}

With this setup in the enum (I think the Operation-part can be trimmed out with Java8), the method will be as simple as:

在枚举中使用此设置(我认为可以使用Java8修剪操作部分),该方法将如下所示:

public static SerializedExpFamMixture rateMtxModel(String model) {
    return Something.fromString(model).getCorrespondingSerializedExpFamMixture();
}

#2


2  

One way you can approach this is to use Reflection:

您可以采用的一种方法是使用Reflection:

Method method = myClass.getClass().getMethod("doSomething", null);
method.invoke(myClass, null);

#3


0  

Use reflection, but you need to consider a few things:

使用反射,但您需要考虑以下几点:

  1. Bug alert! Comparing Strings using == doesn't work as expected in java - use .equals() instead. However, the solution below bypasses that problem
  2. 错误提醒!使用==比较字符串在java中无法正常工作 - 请改用.equals()。但是,下面的解决方案绕过了这个问题

  3. For the general case, which includes methods not visible to the invoker, you need to consider accessibility, both in finding the method and invoking it
  4. 对于包含调用者不可见的方法的一般情况,您需要考虑可访问性,包括查找方法和调用方法

  5. You don't need the result variable, and even if using your code, don't need to initialize it
  6. 您不需要结果变量,即使使用您的代码,也不需要初始化它

Try this:

String methodName = model.replace("(", "").replace(")", "");
try {
    // getMethod() returns only public methods, getDeclaredMethod() returns any visibility
    Method method = SerializedExpFamMixture.class.getDeclaredMethod(methodName);
    // if the method is not guaranteed to be visible (eg public) you need this:
    method.setAccessible(true);
    return (SerializedExpFamMixture) method.invoke(null); // how to invoke on the class object
} catch (Exception forBrevity) {
    return new SerializedExpFamMixture();
}