我想我明白你想在這裏做什麼,你可以用一些元數據和Java 8的Lambda來完成它。
我們要做的是設置一個輔助類,它包含所有由類和ID標識的映射(類似於@GenericMapping,但實際上沒有標註類),幷包含設置和獲取值的方法。對於相同ID的所有映射具有相同的值類型或傳輸值時可能會拋出ClassCastException是很重要的。
我的示例使用三個類,其中並非所有映射都適用於所有類。
下面的代碼:
public class GenericMappingDemo {
static class A {
private Integer integerA;
private String stringA;
private Float floatA;
public A(final Integer integerA, final String stringA, final Float floatA) {
this.integerA = integerA;
this.stringA = stringA;
this.floatA = floatA;
}
public Integer getIntegerA() {
return integerA;
}
public void setIntegerA(final Integer integerA) {
this.integerA = integerA;
}
public String getStringA() {
return stringA;
}
public void setStringA(final String stringA) {
this.stringA = stringA;
}
public Float getFloatA() {
return floatA;
}
public void setFloatA(final Float floatA) {
this.floatA = floatA;
}
@Override
public String toString() {
return "A{integerA=" + integerA + ", stringA='" + stringA + "', floatA=" + floatA + '}';
}
}
static class B {
private Integer integerB;
private String stringB;
public Integer getIntegerB() {
return integerB;
}
public void setIntegerB(final Integer integerB) {
this.integerB = integerB;
}
public String getStringB() {
return stringB;
}
public void setStringB(final String stringB) {
this.stringB = stringB;
}
@Override
public String toString() {
return "B{integerB=" + integerB + ", stringB='" + stringB + '\'' + '}';
}
}
static class C {
private Float floatC;
private String stringC;
public Float getFloatC() {
return floatC;
}
public void setFloatC(final Float floatC) {
this.floatC = floatC;
}
public String getStringC() {
return stringC;
}
public void setStringC(final String stringC) {
this.stringC = stringC;
}
@Override
public String toString() {
return "C{floatC=" + floatC + ", stringC='" + stringC + "'}";
}
}
static class GenericMapping<C, T> {
final int id;
final Class<C> type;
final Function<C, T> getter;
final BiConsumer<C, T> setter;
public GenericMapping(final int id,
final Class<C> type,
final Function<C, T> getter,
final BiConsumer<C, T> setter) {
this.id = id;
this.type = type;
this.getter = getter;
this.setter = setter;
}
}
static class Mapper {
// All mappings by class and id
private final Map<Class<?>, Map<Integer, GenericMapping<?, ?>>> mappings
= new HashMap<>();
public void addMapping(GenericMapping<?, ?> mapping) {
mappings.computeIfAbsent(mapping.type,
c -> new TreeMap<>()).put(mapping.id, mapping);
}
/**
* Map values from one object to another,
* using any mapping ids that apply to both classes
* @param from The object to transfer values from
* @param to The object to transfer values to
*/
public <From, To> void map(From from, To to) {
Map<Integer, GenericMapping<?, ?>> getters
= mappings.get(from.getClass());
Map<Integer, GenericMapping<?, ?>> setters
= mappings.get(to.getClass());
if (getters == null || setters == null) {
// Nothing to do
return;
}
// Create a set with the ids in both getters and
// setters, i.e. the mappings that apply
Set<Integer> ids = new HashSet<>(getters.keySet());
ids.retainAll(setters.keySet());
// Transfer all mappings
for (Integer id : ids) {
GenericMapping<From, ?> getter
= (GenericMapping<From, ?>) getters.get(id);
GenericMapping<To, ?> setter
= (GenericMapping<To, ?>) setters.get(id);
transfer(from, to, getter, setter);
}
}
private <From, To, V> void transfer(final From from,
final To to, final GenericMapping<From, ?> getter,
final GenericMapping<To, V> setter) {
// This will throw an exception if the mappings are invalid
final V value = (V) getter.getter.apply(from);
setter.setter.accept(to, value);
}
}
public static void main(String[] args) {
final Mapper mapper = new Mapper();
// Mapping definition for class A
mapper.addMapping(new GenericMapping<>(1, A.class,
A::getIntegerA, A::setIntegerA));
mapper.addMapping(new GenericMapping<>(2, A.class,
A::getStringA, A::setStringA));
mapper.addMapping(new GenericMapping<>(3, A.class,
A::getFloatA, A::setFloatA));
// Mapping definition for class B
mapper.addMapping(new GenericMapping<>(1, B.class,
B::getIntegerB, B::setIntegerB));
mapper.addMapping(new GenericMapping<>(2, B.class,
B::getStringB, B::setStringB));
// Mapping definition for class C
mapper.addMapping(new GenericMapping<>(2, C.class,
C::getStringC, C::setStringC));
mapper.addMapping(new GenericMapping<>(3, C.class,
C::getFloatC, C::setFloatC));
// Use the mappings
A a = new A(7, "foo", 3.7f);
B b = new B();
C c = new C();
System.out.printf("A before map: %s%n", a);
System.out.printf("B before map: %s%n", b);
System.out.printf("C before map: %s%n", c);
// This will transfer a.integerA to b.integerB and a.stringA to b.stringB
mapper.map(a, b);
// This will transfer a.stringA to c.stringC and a.floatA to c.floatC
mapper.map(a, c);
System.out.println();
System.out.printf("A after map: %s%n", a);
System.out.printf("B after map: %s%n", b);
System.out.printf("C after map: %s%n", c);
}
}
並運行它之後的結果:
A before map: A{integerA=7, stringA='foo', floatA=3.7}
B before map: B{integerB=null, stringB='null'}
C before map: C{floatC=null, stringC='null'}
A after map: A{integerA=7, stringA='foo', floatA=3.7}
B after map: B{integerB=7, stringB='foo'}
C after map: C{floatC=3.7, stringC='foo'}
的Java 7
同樣通用的解決方案,可用於Java 7的,但它會更多詳細信息。由於Java 7沒有功能接口Function<U, V>
和BiConsumer<U, V>
,所以您需要自己定義這些功能,這並不是很麻煩。有人可能會認爲它們也應該在Java 8中定義,因此界面和方法名稱更有意義(例如Getter.get
和Setter.set
)。
最重要的事情是將要使用匿名類來代替lambda表達式的映射定義 - lambda表達式主要是語法糖匿名類只有一個方法反正,但他們使代碼更大量的可讀性。
爲a.integerA的映射看起來會像這樣用Java 7:
mapper.addMapping(new GenericMapping<>(1, A.class,
new Function<A, Integer>() {
@Override
public Integer apply(final A a1) {
return a1.getIntegerA();
}
},
new BiConsumer<A, Integer>() {
@Override
public void accept(final A a1, final Integer integerA) {
a1.setIntegerA(integerA);
}
}));
它並不清楚什麼你想要做的事。您的類名與參數名相同。你的參數被聲明爲具有'Object'類型;他們應該有類型'A'和'B'?什麼是「映射」,因爲你根本不使用它?我懷疑你需要首先學習一些Java基礎知識,因爲可能有一種更簡單的方法來做任何你想做的事情,而不是模仿你在C++中做的事情。 – ajb
他們應該有類型的對象,因爲映射可以是任何類。我將它們命名爲A和B,以表明我打算用A和B類的對象來調用它們。至於我的Java基礎知識,我一直在Java中專業工作了一年多,並且通過了我的Java認證,接近100 %...雖然我同意它可能是我誤解我的意圖(必須愛自閉症)。 –
我們從Java程序員那裏得到很多問題,他們不完全理解如何使用Java的面向對象的概念來模擬他們試圖解決的問題,所以他們試圖用其他機制來解決他們的問題。你沒有提供一個好主意,你想要什麼樣的最終結果,或者你將如何使用你正在嘗試開發的東西(即使你的編輯有一點幫助),所以對我來說很難說這不是那種新的Java程序員問題。我很抱歉........ – ajb