import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

class Ideone {
	
	public static void main(String[] args) throws Throwable {
		ISetter<TestEntity, Long> setter = getSetter(TestEntity.class, "id", Long.class);
		
		TestEntity te = new TestEntity(10L);
		System.out.println(te.getId());
		setter.set(te, 15L);
		System.out.println(te.getId());
	}
	
	public static <T, R> ISetter<T, R> getSetter(Class<T> clazz, String fieldName, Class<R> fieldType) throws Throwable {

	    MethodHandles.Lookup caller = MethodHandles.lookup();
	    MethodType setter = MethodType.methodType(void.class, fieldType);
	    MethodHandle target = caller.findVirtual(clazz, computeSetterName(fieldName), setter);
	    MethodType func = target.type();

	    CallSite site = LambdaMetafactory.metafactory(
	            caller,
	            "set",
	            MethodType.methodType(ISetter.class),
	            func.erase(),
	            target,
	            func
	    );

	    MethodHandle factory = site.getTarget();
	    ISetter<T, R> r = (ISetter<T, R>) factory.invoke();

	    return r;
	}

	public static String computeSetterName(String name) {
		return "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
	}
	
}

interface ISetter<T, R> {
    void set(T object, R value);
}

class TestEntity {

    private Long id;


    public TestEntity(Long id) {
        this.id = id;
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}