private Optional<JavaProperty<?>> merge(List<PartialProperty> pairs) {
			try {
				if (pairs.size() == 1) {
					PartialProperty p = pairs.get(0);
					MethodHandle h = lookup.unreflect(p.m);
					JavaProperty<?> res =
						p.isGetter() ? JavaPropertyFactory.getProperty(p.name, h, null)
								: JavaPropertyFactory.getProperty(p.name, null, h);
					return Optional.of(res);
				}
				PartialProperty g = pairs.stream()
						.filter(PartialProperty::isGetter)
						.findFirst()
						.orElse(null);
				if (g != null) {
					// go through all remaining methods and take the first matching pair
					// it does not matter if one is a boxed primitive and the other is
					// unboxed because the JavaProperty will use the primitive type anyway
					Class<?> target = boxPrimitive(g.m.getReturnType());
					PartialProperty s = pairs.stream()
							.filter(PartialProperty::isSetter)
							.filter(p -> boxPrimitive(p.m.getParameterTypes()[0]) == target)
							.findFirst()
							.orElse(null);
					MethodHandle gh = lookup.unreflect(g.m);
					MethodHandle sh = s != null ? lookup.unreflect(s.m) : null;
					return Optional.of(JavaPropertyFactory.getProperty(g.name, gh, sh));
				}
			}
			catch (IllegalAccessException e) {
				// this is a class in java.lang.invoke or java.lang.reflect
				// the JVM doesn't allow the creation of handles for these
			}
			return Optional.empty();
		}
Helper class for merging methods and removing a layer of reflection
Ghidra/Features/PyGhidra/src/main/java/ghidra/pyghidra/property/PropertyUtils.java