2017-07-19 67 views
-1

來自C++並且目前在Java環境中使用,我想知道如何能夠在Java中創建void *和void *的映射以創建通用從A映射到B並從B映射到A.我知道Java沒有像C++那樣的指針和引用,但是我沒有找到一個仍然允許的方法。將變量從1類映射到另一個類的一般方法

什麼,我想實現的一個例子:

public class A{ 
    @GenericMapping(1) 
    private Integer temp1; 
} 

public class B{ 
    @GenericMapping(1) 
    private Integer temp2; 
} 

public class Mapper{ 
    private List<Pair<Integer, Integer>> mapping; 
    public void map(Object ObjectOfAnyClassButLetsAssumeA, Object ObjectOfAnyClassButLetsAssumeB){ 
     // Get all parameters with GenericMapping above it, get its value 
     // and match the corresponding value with the value of B 
     // Resulting in A.temp1 = B.temp2; 
    } 
} 

然而,如果可能的話我寧願創建地圖(如地圖[A.temp1] = B.temp2),以避免使用@GenericMapping,看到這將允許我不以任何方式修改該類,並仍然便於其映射。

+5

它並不清楚什麼你想要做的事。您的類名與參數名相同。你的參數被聲明爲具有'Object'類型;他們應該有類型'A'和'B'?什麼是「映射」,因爲你根本不使用它?我懷疑你需要首先學習一些Java基礎知識,因爲可能有一種更簡單的方法來做任何你想做的事情,而不是模仿你在C++中做的事情。 – ajb

+0

他們應該有類型的對象,因爲映射可以是任何類。我將它們命名爲A和B,以表明我打算用A和B類的對象來調用它們。至於我的Java基礎知識,我一直在Java中專業工作了一年多,並且通過了我的Java認證,接近100 %...雖然我同意它可能是我誤解我的意圖(必須愛自閉症)。 –

+0

我們從Java程序員那裏得到很多問題,他們不完全理解如何使用Java的面向對象的概念來模擬他們試圖解決的問題,所以他們試圖用其他機制來解決他們的問題。你沒有提供一個好主意,你想要什麼樣的最終結果,或者你將如何使用你正在嘗試開發的東西(即使你的編輯有一點幫助),所以對我來說很難說這不是那種新的Java程序員問題。我很抱歉........ – ajb

回答

1

我想我明白你想在這裏做什麼,你可以用一些元數據和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.getSetter.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); 
      } 
     })); 
+1

這看起來很神奇! :) 我將它標記爲答案,因爲它完全回答了我的問題,但我確實有一個問題:爲了使用Java 7進行此項工作(或者完全不可能),需要更改哪些內容?不幸的是,該公司的代碼還沒有去到Java 8 .. –

+0

謝謝。我更新了關於Java 7的一節。基本上,您只需要定義'Function'和'BiConsumer'接口並將lambda擴展爲匿名類 – Raniz

+0

您是英雄:D –

相關問題