【问题标题】:pass class name via context and use it to store static value in different class通过上下文传递类名并使用它将静态值存储在不同的类中
【发布时间】:2011-06-17 04:27:31
【问题描述】:

对话框和数组显示得很好,我只想能够在onClick 中的原始类中设置静态变量,该类位于不同类中的方法中。所有trycatch<?> 是我在编译器的坚持下放入的:

public class Setter
    {
    public void myList(Context context, Class<?> thisclass, int arrayid, String choice)
        {
        return new AlertDialog.Builder(context)
        .setItems(arrayid, new OnClickListener()
            {
            @Override
            public void onClick(DialogInterface dialog, int which)
                {
                setChoice(thisclass, context, arrayid, which, choice);
                }
            })
        .create();
        }           
    public void setChoice(Class<?> thisclass, Context context, int arrayid, int which, String choice)
        {
        String[] array = context.getResources().getStringArray(arrayid);
        try
            {
            Field f = thisclass.getDeclaredField(choice);
            f.set(null, array[which]);
            }
        catch (SecurityException e)
            {
            e.printStackTrace();
            }
        catch (NoSuchFieldException e)
            {
            e.printStackTrace();
            }
        catch (IllegalArgumentException e)
            {
            e.printStackTrace();
            }
        catch (IllegalAccessException e)
            {
            e.printStackTrace();
            }
        }
    }

public class ClassA extends Activity
    {
    static String stringa;
    Setter setted = new Setter();
    ...
    public void onCreate()
        {
        super.onCreate();
        ...
        AlertDialog thinga = setted.myList(this, getclass(), R.array.thinga, stringa).show();
        ...
        }
    }

当我从列表中选择一个项目时,我会从调试器中得到这个:

ClassCache.findFieldByName(Field[], String) line: 438   
Class.getDeclaredField(String) line: 666    
Setter.setChoice(Class, Context, int, int, String) line: 45 // the line with the Field

我想我把它传错了,但这有点超出我目前的深度。

我有许多不同的班级,每个班级都有自己的static Strings。我在String (在choice 中)和context 的名称下方传递了我希望的原始类,该类调用了一个调用导致下面代码的方法的方法。我希望我可以打电话给context.choice = something,机器会把它读作ClassA.stringa = something;,我该怎么做?

简而言之,我希望有一个用户可以从中选择的项目列表作为对话的内容,并保存它们的选择并可供调用创建对话的类访问。也许我做错了这一切,但我厌倦了处理涉及使用微调器做同样事情的其他“kludges”。

因为onClick 不能在其他地方声明非最终对象(至少这是我的理解),我想也许我可以通过调用另一个方法来解决这个问题,setChoice 将存储任何值选择。我肯定会说这是一个杂牌,我很想知道你应该如何处理这些事情。

【问题讨论】:

  • 对我来说,您的代码有一种奇怪的味道,并且看起来可能是一个混搭。为什么不使用 OOP 技术,创建一个接口并利用多态性的力量调用适当的接口方法呢?另外,为什么是 static 变量?
  • @Hovercraft,事实上他在被调用的方法中设置了调用者的变量,这比气味更糟糕。 stringa=polka; 代替 setted.setChoice(this, stringa, polka); 就足够了。不知何故,他试图抽象出一个赋值语句。
  • @Hovercraft,我在这里见过的最好的名字。您可能是完全正确的,我希望有人将其作为答案之一,如果不是生病的话,必须阅读界面。 @Vineet,我说这是一个极端的简化。我已经用我一般要做什么以及我试图使用这个特定代码做什么来更新问题的底部。

标签: java class methods static closures


【解决方案1】:

Java 没有闭包,但您可以使用匿名内部类。

String output;
public void onCreate() {
    Setter.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            output  = "selected";
        }
    });
}

另请参阅此挥杆教程:http://download.oracle.com/javase/tutorial/uiswing/events/actionlistener.html

编辑: 根据您的示例,这应该如下所示:

public class Setter
{
public void setChoice(IsetString setter, String something)
    {
    setter.setString(something);
    }
}


class ClassA extends Activity implements setString
{
static String stringa;
string polka = "dots";
Setter setted = new Setter();
...
public void onCreate()
    {
    super.onCreate();
    ...
    setted.setChoice(new IsetString() {

        @Override
        public void setString(String s) {
            stringa = s;
        }
    }, polka);
    ...
    }
}

interface IsetString {
    void setString(String s);
}

【讨论】:

  • hrm 我下班后会再看这个,我可能已经浏览了关于接口的章节......
  • 我仍然不完全清楚这个答案对我有什么作用,请原谅我的无知。另外,请参阅上面的编辑,我认为我现在要做的事情要明显得多。
  • 我完全不明白你想做什么。基本上看起来你想用反射来做一些不应该用反射来做的事情。此外,您的问题被半生不熟的使用反射的尝试污染了,我什至无法过滤掉真正的问题。您使用 Context 我不明白,因为您将 ClassA extends Activity 传递给它,您从 Context 中得到一个也不存在的数组。我想您想为某个变量设置某个值,但我不知道它来自哪里以及应该去哪里。
【解决方案2】:

简短的回答 - 使用the Reflection API

长答案 - 您需要获得对所需上下文 ClassFields 的访问权限。一旦获得对 Field 实例的访问权限,就可以使用 set() 方法设置它们的值; API 调用有点棘手,因为您需要传入要修改其字段的对象引用(上下文对象而不是上下文类)。

方法的Contextchoicesomething 参数必须包含必要的信息,以使此操作尽可能简单。换句话说,Context 类可能必须包含包含该字段的实际 Class 对象(或提供一种获取方法)。

【讨论】:

  • 我在黑暗中尝试了使用Field ... 结果几乎是您所期望的。查看编辑。
【解决方案3】:

您可以为此使用反射。假设你的上下文是类本身

public void setChoice(Class<?> context, String choice, String something)
{
   try {
     Field f = context.getDeclaredField(choice);
     f.set(null, something);
   } catch (....) {
   }
}

添加适当的异常处理


注意set 的第一个参数为空。这仅对静态方法有效。因此,您可能需要使用f.getModifiers() 检查该方法是否为静态。

【讨论】:

  • 您可能想说明为什么调用f.set(null, something); 中的第一个参数为空。对于实例成员,这将导致 NullPointerException。
  • 你的似乎是最简单的解决方案,除了当我尝试传递 Class 对象时,我收到以下消息:“类是原始类型。对泛型类型 Class 的引用应该被参数化” 唯一的建议是“推断通用类型参数”或“添加抑制警告”,请问我可以得到更多帮助吗?
  • Class&lt;?&gt; 应该可以工作。无论如何,这只是一个不会停止编译的警告。我在这方面更新了答案。
  • hrm 好的,这似乎是我在我的问题中尝试做的(我更新了它以反映我添加的代码以尝试实现你的建议)我是不是把课程弄错了?
  • 此时我只是不明白您的问题是什么。如果您收到一些编译器错误/警告,请清楚它们。只需将编译器输出添加到问题中即可。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-15
  • 1970-01-01
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 2017-05-02
相关资源
最近更新 更多