【问题标题】:Field Subclass Accessing - Best Way Possible字段子类访问 - 可能的最佳方式
【发布时间】:2013-03-15 18:32:32
【问题描述】:

所以我在处理程序中的首选项时遇到了一些问题。考虑到这将使用的次数,最好使用单一方法。每个变量的吸气剂可能会导致文件更大。

(5 个字段 * 200 到 300 个类 = 大量浪费空间)

我正在尝试弄清楚如何从子类中访问具有已定义和常量名称的字段。

超类是抽象的,定义在一个列表中,我可以完全访问它。这是我希望该领域的吸气剂所在的类。

我希望它的工作方式是这样的:

import java.lang.reflect.Field;

public class Test {

    public Test() {
        final B b = new B();
        final C c = new C();
        System.out.println(b.getFoo());
        System.out.println(c.getFoo());
    }

    public static void main(String[] args) {
        new Test();
    }

    public class A {

        public String getFoo() {
            try {
                Field f = this.getClass().getField("FOO");
                f.setAccessible(true);
                return (String) f.get(null);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

    }

    public class B extends A {

        private static final String FOO = "$HOME.DIR/lib/res/image1.png";

    }

    public class C extends A {

        private static final String FOO = "$HOME.DIR/lib/res/image2.png";

    }

}

不出所料,这不起作用。 A 类不包含字段“FOO”。理想情况下,如果它成功了,我会期望它会打印出来:

$HOME.DIR/lib/res/image1.png
$HOME.DIR/lib/res/image2.png

我(到目前为止)认为这是可能的方式:

  1. 反射
  2. 使用 Getter - 希望避免
  3. 使用注释

使用注释是我认为可行的一种方式,但我通常不喜欢它们的整体概念,但如果这是唯一的方式,我当然会接受它。

感谢您阅读本文,希望您能提供见解。

【问题讨论】:

  • 我想知道为什么将private static final String FOO = "$HOME.DIR/lib/res/image2.png"; 放在子类中比将public String getFOO() { return "$HOME.DIR/lib/res/image2.png"} 放在子类中更容易,因为两者的字符长度大致相同并且都可以通过剪切/粘贴/键入所有 200-300 个子类。 (您可以使用一个属性文件,其中的所有字符串都由类的名称索引,例如 B=$HOME.DIR/lib/res/image2.png 和 A 中的 getFoo() 方法。)
  • 这既是为了学习、扩展(希望开放 API),也是为了真正消除混乱。我真的只是将private static final 放在前面用于演示目的,但根本不需要这些。它只会有一个实例,所以不需要像那样只维护一个变量。

标签: java reflection annotations field getter


【解决方案1】:

您能否更详细地描述您的更高级别的问题,因为听起来您可以进行一些设计更改来缓解此问题。通过反射从父类访问子类的字段通常似乎是个坏主意。

但是,话虽如此,您需要使用getDeclaredField 而不是getField 才能通过反射访问私有字段。

例如

public String getFoo() {
        try {
            Field f = this.getClass().getDeclaredField("FOO");
            f.setAccessible(true);
            return (String) f.get(null);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
}

【讨论】:

  • 即使从静态更改并使用 getDeclaredField 也失败了,遗憾的是。正如我在上面的课程中指出的那样,数据类型的最终修订可以归结为:String foo = "this";
  • 以上内容适用于静态。如果使用非静态,则需要将实例传递给 f.get 而不是 null。
  • @Legend,我将您上面的代码更改为只有 getDeclaredField 并且它工作得很好......
  • @Legend,你上面的代码不需要这个,但是是的,如果你想访问非静态的东西,你需要指定要使用的实例,这是传递给你的实例案例。
  • 这应该真的被视为最后的手段。可能在编辑现有类时绝对是不可能的。反射是强大的,但出了名的慢,应该明智地使用。它的另一个问题是它不是重构安全的,即如果您将 FOO 的名称更改为其他名称,您的 IDE 将不会修改 A 类中的代码。如果你只是在尝试,那就继续玩吧……
【解决方案2】:

您可以使用地图,如下所示:

import java.util.HashMap;
import java.util.Map;

public class Test 
{
    public Test() 
    {
        final B b = new B();
        final C c = new C();
        System.out.println(b.getFoo());
        System.out.println(c.getFoo());
    }

    public static void main(String[] args)
    {
        new Test();
    }
}

class A 
{
    private static final Map<String, String> values;

    static
    {
        values = new HashMap<String, String>();
    }

    public String getFoo() 
    {
        return (values.get("FOO"));
    }

    protected static void addValue(final String key,
                                  final String value)
    {
        values.put(key, value);
    }
}

class B extends A 
{
    static
    {
        addValue("FOO", "$HOME.DIR/lib/res/image1.png");
    }
}

class C extends A 
{
    static
    {
        addValue("FOO", "$HOME.DIR/lib/res/image2.png");
    }
}

【讨论】:

    猜你喜欢
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多