简体   繁体   English

使用字符串查找 static 变量 Java

[英]Using a String to find a static variable Java

I need to find a way to use a String, to get the value of a variable, in a another class. For instance, say I had this class:我需要找到一种方法来使用字符串来获取另一个 class 中的变量值。例如,假设我有这个 class:

public class ClassName {
   public static File f = new File ("C:\\");
}

And I also had this String in a different class:我还在另一个 class 中有这个字符串:

String str = "ClassName.f";

Is there a way I could use the String, str, to get the value of ClassName.f?有没有一种方法可以使用字符串 str 来获取 ClassName.f 的值? I don't want to have to hard code each value into a specific method.我不想将每个值硬编码到特定方法中。

Assuming you always only want static fields, the following code does some string splitting and uses reflection to do this. 假设您始终只需要静态字段,下面的代码将进行一些字符串拆分,并使用反射进行此操作。 It will print "oy" when run... 运行时它将显示“ oy”。

import java.lang.reflect.Field;

public class StackOverflow {

    public static String oy = "OY";

    public static void main(String[] args) {
        System.out.println(getStaticValue("StackOverflow.oy"));
    }

    public static Object getStaticValue(String fieldId) {
        int idx = fieldId.indexOf(".");
        String className = fieldId.substring(0, idx);
        String fieldName = fieldId.substring(idx + 1);

        try {
            Class<?> clazz = Class.forName(className);
            Field field = clazz.getDeclaredField(fieldName);
            return field.get(null);
        } catch(Exception ex) {
           // BOOM!
            ex.printStackTrace();
        }

        return null;
    }
}

If your static field is not public, you will need to make it accessible, to do this, you need to add the "setAccessible" line... 如果您的静态字段不是公共字段,则需要使其可访问,为此,您需要添加“ setAccessible”行...

import java.lang.reflect.Field;

public class StackOverflow {

    private static String oy = "OY";

    public static void main(String[] args) {
        System.out.println(getStaticValue("StackOverflow.oy"));
    }

    public static Object getStaticValue(String fieldId) {
        int idx = fieldId.indexOf(".");
        String className = fieldId.substring(0, idx);
        String fieldName = fieldId.substring(idx + 1);

        try {
            Class<?> clazz = Class.forName(className);
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(null);
        } catch(Exception ex) {
           // BOOM!
            ex.printStackTrace();
        }

        return null;
    }
}

Use reflection : 使用反射

// make array to use easier
String[] str = "ClassName.f".split("\\.");

// get the class
Class c = Class.forName("packagename." + str[0]);
// get the field
Field field = c.getDeclaredField(str[1]);

// USE IT!
System.out.println(field.getName());

OUTPUT: 输出:

f

A map, as suggested in the comments, could be your best bet, as in this case reflection might not be the best practice. 评论中建议的地图可能是您最好的选择,因为在这种情况下,反思可能不是最佳实践。

To be able to call it from anywhere in your program, you'd need something like the Singleton pattern, which has to be handled with care: 为了能够从程序的任何地方调用它,您需要类似Singleton模式之类的东西,必须谨慎处理:

public class ClassNameHandler {
   private static ClassNameHandler instance = null;
   protected ClassNameHandler() {
      // Exists only to defeat instantiation.
   }

   public Map<String, File> map = new HashMap<String, File>();

   public File f = ClassName.f;
   map.put("ClassName.f", f);
   //Add more files or variables to the map

   public static ClassNameHandler getInstance() {
      if(instance == null) {
         instance = new ClassNameHandler();
      }
      return instance;
   }
}

Then, elsewhere, you could use something like : 然后,在其他地方,您可以使用类似:

String str = "ClassName.f";
ClassNameHandler.map.get(str);

Double check the singleton pattern for implementation. 仔细检查单例模式的实现。 If it sounds like too much, then there may be other options available but you did not provide much context or what the purpose of your application is, so it depends. 如果听起来太多,那么可能还有其他选项可用,但是您没有提供太多上下文或应用程序的用途是什么,所以这取决于。

I needed something like this as part of injecting api keys into Unity3d via Android apps我需要这样的东西作为通过 Android 应用程序将 api 密钥注入 Unity3d 的一部分

Thanks to some of the answers here I came up with:感谢这里的一些答案,我想出了:

inside OnCreateOnCreate里面

tryPutExtra("SECRET_API_STUFF");

tryPutExtra function tryPutExtra function

void tryPutExtra(String prop) {
    try {
        Field field = BuildConfig.class.getDeclaredField(prop);
        String str = String.valueOf(field);
        getIntent().putExtra(prop, str);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}

** EDIT ** ** 编辑 **

At some point the the above function stopped working and I don't know why.在某些时候,上面的 function 停止工作,我不知道为什么。 I've migrated to the following:我已经迁移到以下内容:

    try {
        Field field = BuildConfig.class.getDeclaredField(prop);
        // String str = String.valueOf(field);
        String str = field.get(null).toString();
        intent.putExtra(prop, str);
        Log.i(null, "PutExtra " + prop + " = " + str);
        field.setAccessible(true);
    } catch (Exception e) {
        e.printStackTrace();
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM