2014-09-01 10 views
6

मैंने सोचा कि यह अपेक्षाकृत आसान होगा, लेकिन हां, ऐसा लगता है कि यह नहीं है।डबल ब्रेस प्रारंभिकता प्रकार भ्रम

मैं वर्तमान में जावा ईई 6.
का उपयोग कर टेस्ट मैं JUnit 4.11 उपयोग करते हैं, आईडीई के रूप में ग्रहण केपलर के साथ के लिए मेरी परियोजना में एक फसाड की तरह संरचना के लिए यूनिट टेस्ट लिख रहा हूँ।

जो मैं देख सकता हूं, वहां से डबल ब्रेस प्रारंभिकता के साथ कुछ "गलत" लगता है, लेकिन मुझे पर मेरी उंगली डालने के लिए पर्याप्त जानकारी नहीं है क्यों यह काम नहीं करता है जैसा मुझे लगता है कि यह चाहिए।

बात करने के लिए प्राप्त करने के लिए, मैं निम्नलिखित वर्ग का उपयोग कर रहा एक केंद्रीकृत स्थान में रूपांतरण बनाने के लिए:

package com.example-company.util.converters; 

import java.util.HashMap; 
import java.util.Map; 

import com.example-company.model.Location; 
import com.example-company.model.Right; 

public final class ModelConverters { 

    private static final Map<Class<?>, ModelConverter<?, String>> modelConverterBacking = new HashMap<Class<?>, ModelConverter<?, String>>(); 
    static { 
     modelConverterBacking.put(Right.class, new RightConverter()); 
     modelConverterBacking.put(Location.class, new LocationConverter()); 
    }; 

    public static <T> String convert(final T input) 
      throws IllegalStateException { 
     @SuppressWarnings("unchecked") 
     ModelConverter<T, String> modelConverter = (ModelConverter<T, String>) modelConverterBacking 
       .get(input.getClass()); 
     if (modelConverter == null) { 
      throw new IllegalStateException("No mapping found for " 
        + input.getClass()); 
     } 
     return modelConverter.convertToView(input); 
    } 
} 

जहां तक ​​इस चला जाता है यह ज्यादातर जेनरिक और एक स्थिर नक्शे के साथ खेल रहा है। अब मैंने फैसला किया कि मुझे इसके लिए कुछ यूनिट-टेस्ट लिखना चाहिए। निम्नलिखित वर्ग थोड़ा छोटा है, सभी टेस्ट-केस जो समस्या को पुन: उत्पन्न नहीं करते हैं उन्हें हटा दिया गया था।

package com.example-company.test.unit.util.converters; 

import static org.junit.Assert.assertEquals; 
import com.example-company.model.Location; 
import com.example-company.util.converters.ModelConverters; 

import org.junit.Test; 

public class ModelConvertersFacadeTests { 

    @Test 
    public void test_MappingForLocationExists() { 
     final Location stub = new Location() { 
      { 
       setLocationName(""); 
      } 
     }; 

     String actual = ModelConverters.convert(stub); 
     assertEquals("", actual); 
    } 
} 

अब तक इतना अच्छा है, वास्तव में कुछ भी नहीं होना चाहिए, कम से कम मुझे जो मिला है। और वह है: निम्नलिखित स्टैकट्रेस के साथ एक फैंसी IllegalStateException:

java.lang.IllegalStateException: No mapping found for class com.example-company.test.unit.util.converters.ModelConvertersFacadeTests$1 
    at com.example-company.util.converters.ModelConverters.convert(ModelConverters.java:23) 
    at com.example-company.test.unit.util.converters.ModelConvertersFacadeTests.test_MappingForLocationExists(ModelConvertersFacadeTests.java:24) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

पहली बात मैंने किया था, यह फिर से चलाया गया था, और फिर एक ब्रेकपाइंट की स्थापना का निरीक्षण करने के क्या ModelConverters#convert()

अंदर होता है क्या मैं थोड़ा flabberghasted गया मैं:

Debug Perspective: Expressions

ऐसा लगता है कि input.getClass() फिर से ModelConvertersFacadeTests बदलता है। लेकिन यह com.example-company.model.Location क्यों नहीं लौटाता है?

Full Debug Perspective, names censored

+0

[आपको आमतौर पर डबल ब्रेस प्रारंभिकरण का उपयोग करने से सावधान रहना चाहिए] (http://stackoverflow.com/q/924285/521799) –

उत्तर

13

ऐसा लगता है कि input.getClass() ModelConvertersFacadeTests

सच नहीं है कि देता है। आपका स्टैकट्रेस कहते हैं इस वर्ग है:

com.example-company.test.unit.util.converters.ModelConvertersFacadeTests $ 1

नोट $1 अंत में। इसका मतलब है कि आपकी कक्षा एक अज्ञात है (इसका अपना नाम नहीं है) आंतरिक वर्ग।

this$0 जो हम आपके स्क्रीनशॉट में देखते हैं वह बाहरी कक्षा में संदर्भ है।

हर बार जब आप new SomeClass() { ... } करते हैं तो आप एक अज्ञात आंतरिक कक्षा बना रहे हैं।

डबल ब्रेस प्रारंभिकरण के पास इसके साथ कुछ लेना देना नहीं है।हर बार जब आप डबल ब्रेस प्रारंभिकरण का उपयोग कर रहे हैं, तो आप एक अज्ञात भीतरी कक्षा बना रहे हैं।


सुलझाने अलग ढंग से

आपका Map नक्शे में ऊपर देखकर भी Right.class और Location.class के लिए एक मानचित्रण है, लेकिन यह उपवर्गों इन दो वर्गों के के लिए एक मानचित्रण जरूरत नहीं है।

static { 
    modelConverterBacking.put(Right.class, new RightConverter()); 
    modelConverterBacking.put(Location.class, new LocationConverter()); 
}; 

क्या आप सकता करते (नहीं हुए कहा कि यह सबसे अच्छा तरीका है), जाँच अपने नक्शे के कुंजी और लूप करने के लिए है:

mapKey.isAssignableFrom(input.getClass()) 

जब यह सच देता है, आप जानते हैं आपके पास या तो mapKey का वर्ग है या आपके पास इसका सबक्लास है।

नक्शा कुंजी के माध्यम से लूप करने के बजाय, आप सुपरक्लास के माध्यम से लूप भी कर सकते हैं और आपके द्वारा पारित ऑब्जेक्ट के इंटरफ़ेस को कार्यान्वित कर सकते हैं, और उनमें से प्रत्येक के लिए modelConverterBacking.get लुकअप कर सकते हैं। प्रभाव वही होगा।


एक गुमनाम आंतरिक वर्ग का उपयोग किए बिना सुलझाने

आपकी वर्तमान कोड है:

final Location stub = new Location() { 
    { 
     setLocationName(""); 
    } 
}; 

तो आप के बजाय करना होगा:

final Location stub = new Location(); 
stub.setLocationName(""); 

तो फिर तुम किसी भी निर्माण नहीं करतीं गुमनाम आंतरिक वर्ग और इसलिए इस समस्या नहीं होगी।

हालांकि, आप बस यह करने के भले ही:

final Location stub = new Location() {}; 
stub.setLocationName(""); 

तो फिर तुम एक गुमनाम आंतरिक वर्ग है, जो आप के लिए समस्याएं पैदा होगा।


यह बहुत महत्वपूर्ण दो वर्गों ModelConvertersFacadeTests$1 और ModelConvertersFacadeTests अप मिश्रण नहीं है।

संबंधित मुद्दे