有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java我可以提供一个接口来允许另一个类让我访问它的私有变量吗?

首先,澄清一下:所谓“接口”,我指的是组件之间的任何交互点,不一定是“抽象类型”的接口。(虽然如果我能使用这样的界面来实现这一点,那就太好了。)

我正在写一个扩展类。问题域是全局优化,因此任何将我的类划分为子类的最终用户程序员(我称他们为Steve)都将提供他们自己的问题和算法来解决它;我只提供框架(网络、用户界面等)。Steve的程序可能需要任意数量的配置设置;我希望我的代码能够像从GUI控制面板、XML配置文件或其他任何地方获取设置一样,从用户那里获取这些设置。Steve不应该复制我的任何代码,也不应该破坏Java的类型安全或封装模型

理想情况下,Steve能够按照以下思路写一些东西:

public class SteveClass extends MyFrameworkClass {

    @Configurable
    private int foo;

    @Configurable
    private String bar;

    private boolean baz;

    // implementations of my abstract methods, etc.

}

Configurable是我将提供的一个注释,它指示带注释的变量是我应该从用户那里获得的配置设置。正如你们所看到的,我还希望Steve能够声明其他实例变量,供他自己内部使用,这是我从未接触过的

我打算通过在MyFrameworkClass中包含一个方法来实现这一点,该方法将遍历getClass().getDeclaredFields(),并标识具有Configurable注释的字段。然后,它会将用户输入写入这些字段。它不必看起来完全像这样,有注释等等,但是你明白了

当然,这方面的问题是foobar是私有的,MyFrameworkClass中的代码不能写入它们,甚至不能反射。如果它们是包私有的,那就没用了,因为Steve的代码不会和我的代码在同一个包中,我不希望他将它们公开,或者添加任何其他接口,允许除我之外的任何人访问这些字段

有没有什么方法可以做我想做的事,要么摆弄SecurityManager,要么做一些完全不同的事情


共 (3) 个答案

  1. # 1 楼答案

    1. 创建一个配置界面

      interface Configuration
      {
          int foo ( ) ;
      
          String bar ( ) ;
      }
      
    2. 使用配置界面

      public class SteveClass extends MyFrameworkClass {
          private Configuration configuration ;
      
          // implementations of my abstract methods, etc.
      
      }
      

    我认为这叫做授权

  2. # 2 楼答案

    您可以使用Class.getDeclaredFields来获取类的所有声明字段(包括非公共字段),然后使用Field.setAccessible(true)来访问它

    Field foo = HasPrivate.class.getDeclaredField("foo");
    foo.setAccessible(true);
    SteveClass steve = new SteveClass();
    System.out.println(steve); // "0"   I set up SteveClass.toString() to just print foo
    foo.setInt(hp, 1234);
    System.out.println(steve); // "1234"
    

    但这意味着您需要依靠SecurityManager才能做到这一点。默认情况下是这样,但这可能不适用于所有用户。如果这是一个禁止性的要求,那么还有其他不太方便但可能更健壮的选项(比如要求构造函数获取配置对象,然后用户可以从中获取值)

  3. # 3 楼答案

    如果我处在你的位置,我会试图找到一种方法来使用Spring框架为我做到这一点。这样用户就可以写下:

    @Component
    public class SteveClass {
        @Value("${steve.foo}")
        private int foo;
    
        @Value("${steve.bar}")
        private String bar;
    
        private boolean baz;
    
        @Autowired(required = false)
        private DaveClass dave;
    }
    

    然后,你所要做的就是构建一个包含这些属性的上下文;这太微不足道了。(Spring确实会在安全场景的背后进行探索,但它是以“正确”的方式进行的;您所需要做的就是确保Spring是可信的,您的其余代码不需要几乎相同级别的权限。)当然,它也为史蒂夫提供了许多其他工具来帮助他构建应用程序,但这是另一个问题的故事