109

Is it possible in Java to access private field str via reflection? For example to get value of this field.

class Test
{
   private String str;
   public void setStr(String value)
   {
      str = value;
   }
}
Volodymyr Bezuglyy
  • 16,295
  • 33
  • 103
  • 133

3 Answers3

194

Yes, it absolutely is - assuming you've got the appropriate security permissions. Use Field.setAccessible(true) first if you're accessing it from a different class.

import java.lang.reflect.*;

class Other
{
    private String str;
    public void setStr(String value)
    {
        str = value;
    }
}

class Test
{
    public static void main(String[] args)
        // Just for the ease of a throwaway test. Don't
        // do this normally!
        throws Exception
    {
        Other t = new Other();
        t.setStr("hi");
        Field field = Other.class.getDeclaredField("str");
        field.setAccessible(true);
        Object value = field.get(t);
        System.out.println(value);
    }
}

And no, you shouldn't normally do this... it's subverting the intentions of the original author of the class. For example, there may well be validation applied in any situation where the field can normally be set, or other fields may be changed at the same time. You're effectively violating the intended level of encapsulation.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    There are very few instances where you should do this, as Jon noted. I have unfortunately had to do it more than I care to admit, and it makes for VERY ugly code. – aperkins Oct 12 '09 at 17:01
  • FAIL. If you remove the call to `setAccessible` it still works, even with a security manager present. :) But +1 for "you shouldn't normally do this". – Tom Hawtin - tackline Oct 12 '09 at 17:36
  • @Tom: Thanks, fixed up the example to a situation where you *do* need to do it :) – Jon Skeet Oct 12 '09 at 18:01
  • 1
    Nice correction. (See Guideline 6-4 of Secure Coding Guidelines Version 2.0 for the Java Programming Language: http://java.sun.com/security/seccodeguide.html ) – Tom Hawtin - tackline Oct 12 '09 at 18:03
  • 14
    @Downvoter: Care to explain why? – Jon Skeet Nov 01 '09 at 07:51
  • @JoseMartinez: If you don't know the name of the variable, I don't see how *this* question is relevant. Perhaps you ought to ask a new question which explains what you're trying to achieve. – Jon Skeet May 06 '14 at 15:32
  • @JonSkeet I think it is relevant.... the question is accessing private fields using reflections. In your answer the user must have the name of the variable. Another variation is where the user does not have the name of the variable. But I did find the answer... just call the getDeclaredFields() method without any arguments to get the Field[]. Thanks! – Jose Martinez May 06 '14 at 15:35
  • @JoseMartinez: Well in the OP's question, they're clearly aware of the name. If you don't know what variable you're trying to access, you can get *all* of them, but you'd still need to work out which one you were interested in... – Jon Skeet May 06 '14 at 15:37
  • This answer would provide more value, if you could elaborate **why** *"you shouldn't normally do this..."* – Angelo.Hannes Sep 15 '14 at 11:24
  • @Angelo.Hannes: See if my edit (just an elaboration at the bottom) helps. – Jon Skeet Sep 15 '14 at 12:03
  • `a.setAccessible(true); String var = a.getName(); a.get(var)` gives me `Can not set final to java.lang.String` – Ava Dec 08 '14 at 19:21
  • @Ava: Interesting - it still works for me. Depends on the JVM, I suspect. Or maybe I'm mosunderstanding your example... – Jon Skeet Dec 08 '14 at 19:33
  • 1
    @JonSkeet why java allow this to access private members? why java created `setAccessible()` method? – Asif Mushtaq Apr 24 '16 at 10:42
  • @JonSkeet this method doesn't seem to work when I do It multiple times (3 being the number). I have some more info on it here: bukkit.org/threads/how-to-get-private-field-java-8.422602/#post-3392416 – Roke Jun 23 '16 at 21:21
  • @RookieTEC9: You should post a new question on Stack Overflow, with a short but complete example, and the full stack trace. – Jon Skeet Jun 23 '16 at 21:27
  • @JonSkeet I am in the process of doing so. – Roke Jun 23 '16 at 21:36
  • I guess ORM is perfect use case to use this, even if you don't know the field name, you can always enumerate. – suresh Nov 21 '16 at 05:08
  • Why is this feature allowed? To a novice like me, it seems like a clear violation of OOP principles. – Islam Hassan Jan 08 '19 at 15:49
  • 1
    @IslamEl-Rougy: Reflection is quite often a pragmatic solution for otherwise annoying situations. It's definitely worth avoiding where possible, and is often a *bad* solution. I don't know whether I'd go so far as to prohibit it entirely, but I'd always at least be nervous. – Jon Skeet Jan 08 '19 at 16:20
  • 1
    Note for posterity: JPMS modules add more encapsulation regarding reflection; now the package must be `opens` to at least the caller module (if using modules). – Slaw Apr 07 '20 at 21:28
56

Yes.

  Field f = Test.class.getDeclaredField("str");
  f.setAccessible(true);//Very important, this allows the setting to work.
  String value = (String) f.get(object);

Then you use the field object to get the value on an instance of the class.

Note that get method is often confusing for people. You have the field, but you don't have an instance of the object. You have to pass that to the get method

Yishai
  • 90,445
  • 31
  • 189
  • 263
5

Yes it is possible.

You need to use the getDeclaredField method (instead of the getField method), with the name of your private field:

Field privateField = Test.class.getDeclaredField("str");

Additionally, you need to set this Field to be accessible, if you want to access a private field:

privateField.setAccessible(true);

Once that's done, you can use the get method on the Field instance, to access the value of the str field.

pythonquick
  • 10,789
  • 6
  • 33
  • 28