How to read the value of a private field from a different class in Java?

前端 未结 14 1705
梦毁少年i
梦毁少年i 2020-11-21 11:28

I have a poorly designed class in a 3rd-party JAR and I need to access one of its private fields. For example, why should I need to choose priv

相关标签:
14条回答
  • 2020-11-21 11:50

    As oxbow_lakes mentions, you can use reflection to get around the access restrictions (assuming your SecurityManager will let you).

    That said, if this class is so badly designed that it makes you resort to such hackery, maybe you should look for an alternative. Sure this little hack might be saving you a few hours now, but how much will it cost you down the road?

    0 讨论(0)
  • 2020-11-21 11:52

    Try to go around the problem for the case, the calass of which you want to set/get data is one of your own classes.

    Just create a public setter(Field f, Object value) and public Object getter(Field f) for that. You can even do some securoty check on your own inside theses member functions. E.g. for the setter:

    class myClassName {
        private String aString;
    
        public set(Field field, Object value) {
            // (A) do some checkings here  for security
    
            // (B) set the value
            field.set(this, value);
        }
    }
    

    Of course, now you have to find out the java.lang.reflect.Field for sString prior to setting of field value.

    I do use this technique in a generic ResultSet-to-and-from-model-mapper.

    0 讨论(0)
  • 2020-11-21 11:53

    You can use jOOR for that.

    class Foo {
        private final String value = "ABC";
    }
    class Bar {
        private final Foo foo = new Foo();
        public String value() {
            return org.joor.Reflect
                .on(this.foo)
                .field("value")
                .get();
        }
    }
    class BarTest {
        @Test
        void accessPrivateField() {
            Assertions.assertEquals(new Bar().value(), "ABC");
        }
    }
    
    0 讨论(0)
  • 2020-11-21 11:54

    Use the Soot Java Optimization framework to directly modify the bytecode. http://www.sable.mcgill.ca/soot/

    Soot is completely written in Java and works with new Java versions.

    0 讨论(0)
  • 2020-11-21 11:57

    It is quite easy with the tool XrayInterface. Just define the missing getters/setters, e.g.

    interface BetterDesigned {
      Hashtable getStuffIWant(); //is mapped by convention to stuffIWant
    }
    

    and xray your poor designed project:

    IWasDesignedPoorly obj = new IWasDesignedPoorly();
    BetterDesigned better = ...;
    System.out.println(better.getStuffIWant());
    

    Internally this relies on reflection.

    0 讨论(0)
  • 2020-11-21 12:00

    Reflection isn't the only way to resolve your issue (which is to access the private functionality/behaviour of a class/component)

    An alternative solution is to extract the class from the .jar, decompile it using (say) Jode or Jad, change the field (or add an accessor), and recompile it against the original .jar. Then put the new .class ahead of the .jar in the classpath, or reinsert it in the .jar. (the jar utility allows you to extract and reinsert to an existing .jar)

    As noted below, this resolves the wider issue of accessing/changing private state rather than simply accessing/changing a field.

    This requires the .jar not to be signed, of course.

    0 讨论(0)
提交回复
热议问题