Add a value cache to avoid redundant lookups

Benchmark results:
  Uncached:
    intPojo: 5 ms
    finalIntPojo: 1 ms
    intField: 206 ms
    stringPojo: 6 ms
    finalStringPojo: 2 ms
    stringField: 208 ms

  Cached:
    intPojo: 7 ms
    finalIntPojo: 3 ms
    intField: 33 ms
    stringPojo: 7 ms
    finalStringPojo: 2 ms
    stringField: 23 ms