2013-03-28 18 views
16

निम्न कोड जावा 1.6 में ठीक है, लेकिन जावा 1.7 में संकलित करने में विफल रहता है। क्यूं कर?जावा 1.6 में यह कोड संकलित क्यों करता है लेकिन जावा 1.7 में नहीं?

कोड का प्रासंगिक भाग निजी 'डेटा' फ़ील्ड का संदर्भ है। संदर्भ उसी वर्ग के भीतर से है जिसमें फ़ील्ड परिभाषित किया गया है, और ऐसा लगता है कि कानूनी है। लेकिन यह एक सामान्य रूप से टाइप किए गए चर के माध्यम से हो रहा है। यह कोड - इन-हाउस लाइब्रेरी से कक्षा के आधार पर एक छीन लिया गया उदाहरण - जावा 1.6 में काम किया लेकिन अब जावा 1.7 में नहीं है।

मैं यह नहीं पूछ रहा हूं कि इस के आसपास कैसे काम करना है। मैंने पहले ही ऐसा कर लिया है। मैं एक स्पष्टीकरण खोजने की कोशिश कर रहा हूं कि यह अब और क्यों काम नहीं करता है। तीन संभावनाएं मन में आते हैं:

  • इस कोड नहीं कानूनी JLS के अनुसार है और कभी नहीं तैयार की है चाहिए
  • इस कोड कानूनी है (वहाँ 1.6 संकलक में एक बग, 1.7 में ठीक किया गया था) JLS के अनुसार और (एक पश्चगामी संगतता बग 1.7 संकलक में शुरू किया गया है)
  • इस कोड JLS
में एक ग्रे क्षेत्र में गिर जाता है संकलन चाहिए

Foo.java:

import java.util.TreeMap; 
import java.util.Map; 

public abstract class Foo<V extends Foo<V>> { 

    private final Map<String,Object> data = new TreeMap<String,Object>(); 

    protected Foo() { ; } 

    // Subclasses should implement this as 'return this;' 
    public abstract V getThis(); 

    // Subclasses should implement this as 'return new SubclassOfFoo();' 
    public abstract V getEmpty(); 

    // ... more methods here ... 

    public V copy() { 
     V x = getEmpty(); 
     x.data.clear();  // Won't compile in Java 1.7 
     x.data.putAll(data); // " 
     return x; 
    } 

} 

संकलक उत्पादन:

> c:\tools\jdk1.6.0_11\bin\javac -version 
javac 1.6.0_11 

> c:\tools\jdk1.6.0_11\bin\javac c:\temp\Foo.java 

> c:\tools\jdk1.7.0_10\bin\javac -version 
javac 1.7.0_10 

> c:\tools\jdk1.7.0_10\bin\javac c:\temp\Foo.java 
Foo.java:18: error: data has private access in Foo 
     x.data.clear(); 
     ^
Foo.java:19: error: data has private access in Foo 
     x.data.putAll(data); 
     ^
2 errors 

परिशिष्ट। एक ही समस्या तब होती है जब संदर्भ किसी निजी सदस्य चर के बजाय निजी विधि के लिए होता है। यह जावा 1.6 में काम करता है लेकिन 1.7 में नहीं।

Foo2.java:

import java.util.TreeMap; 
import java.util.Map; 

public abstract class Foo2<V extends Foo2<V>> { 

    private final Map<String,Object> data = new TreeMap<String,Object>(); 

    protected Foo2() { ; } 

    // Subclasses should implement this as 'return this;' 
    public abstract V getThis(); 

    // Subclasses should implement this as 'return new SubclassOfFoo();' 
    public abstract V getEmpty(); 

    // ... more methods here ... 

    public V copy() { 
     V x = getEmpty(); 
     x.theData().clear();  // Won't compile in Java 1.7 
     x.theData().putAll(data); // " 
     return x; 
    } 

    private Map<String,Object> theData() { 
     return data; 
    } 

} 

संकलक उत्पादन:

> c:\tools\jdk1.6.0_11\bin\javac c:\temp\Foo2.java 

> c:\tools\jdk1.7.0_10\bin\javac c:\temp\Foo2.java 
Foo2.java:18: error: theData() has private access in Foo2 
     x.theData().clear(); 
     ^
Foo2.java:19: error: theData() has private access in Foo2 
     x.theData().putAll(data); 
     ^
+0

मैं दोनों जेनरेट की गई कक्षा फ़ाइलों को विघटित करने का सुझाव दूंगा, तो अंतर स्पष्ट होना चाहिए। – Landei

+0

@Landei 1.7 मामले में कोई जेनरेट क्लास फ़ाइल नहीं है, क्योंकि संकलक इसे संकलित करने से इंकार कर देता है। –

उत्तर

18

प्रदर्शन मुद्दा व्यवहार Oracle bug 6904536 की रिपोर्ट में मैच के लिए लगता है। निम्नलिखित स्पष्टीकरण के साथ बग को "कोई समस्या नहीं" के रूप में बंद कर दिया गया था:

जावैक जेएलएस के अनुसार व्यवहार कर रहा है। 6558551, 6711619 और संबंधित जेएलएस समस्या 6644562 देखें।

इसी JLS समस्या का समाधान नहीं है, तो निम्न टिप्पणी के साथ:

प्रकार चर की सदस्यता के लिए एक सरलीकृत विवरण का स्वागत है। परिवर्तनीय सीमाओं के निजी सदस्यों के साथ एक सामान्य कठिनाई है।औपचारिक रूप से इस तरह के सदस्यों प्रकार चर खुद के सदस्यों नहीं हो जाते, हालांकि javac और ग्रहण पारंपरिक रूप से उन्हें सदस्यों बनाया और कोड है कि पर भरोसा करने के लिए आ गया है:

class Test { 
    private int count = 0; 
    <Z extends Test> void m(Z z) { 
    count = z.count; // Legal in javac 1.6, illegal in javac 1.7 due to fix for 6711619 
    } 
} 

पीटर एक समान परीक्षण प्रस्तुत:

class A { 
    static class B { private String f; } 

    abstract static class Builder<T extends B> { 
    abstract T getB(); 

    { 
     ((B)getB()).f.hashCode(); 
     getB().f.hashCode(); // error: f has private access in A.B 
    } 

    } 
} 

चूंकि छेड़छाड़ के प्रकार विरासत द्वारा बनाए जाते हैं, और निजी सदस्यों को कभी विरासत में नहीं मिला है, निजी सदस्यों के लिए चौराहे प्रकारों को फिर से निर्दिष्ट करना मुश्किल है। फिर भी, यह संगत करने के लिए संगत होगा।

संदर्भ के लिए, जेएलएस का प्रासंगिक खंड §4.4 है।

संपादित करें:

मैं यहाँ वास्तव में, क्योंकि यह अपने आप से मेल खाए JLS से सहमत होना, जब हम तस्वीर से जेनरिक को दूर करते हैं। इस उदाहरण पर विचार: क्योंकि निजी सदस्यों के लिए उपयोग विरासत में मिला नहीं है

static class Parent { 

    private int i; 

    void m(Child child) { 
     i = child.i; //compile error 
    } 
} 

static class Child extends Parent { } 

child.i दिखाई नहीं देता है।

void m(Child child) { 
    i = ((Parent)child).i; 
} 
साथ

तो विरासत में मिला:

static class Child extends Parent { 
    private int i; //totally fine 
} 

तो यह की upcasting आवश्यक किया जा रहा है एक दुर्लभ उदाहरण होगा: इस बिंदु तथ्य Child किसी भी छाया के बिना अपने स्वयं के i हो सकता है द्वारा घर संचालित है तस्वीर से सुलभता, जेएलएस यहां सही लगता है, VFoo<V extends Foo<V>> में Foo<V> आवश्यक नहीं है लेकिन Foo<V> तक कुछ प्रकार का हो सकता है।

+0

धन्यवाद पॉल। हां, इसका जवाब यह है कि 6 में जेवाक कुछ ऐसे रूपों को संकलित करता है जो जेएलएस के साथ सख्त अनुरूप नहीं थे, उपर्युक्त उदाहरण है। 7 में जावैक ने इसे ठीक कर दिया है। विशेष रूप से, एक सामान्य संदर्भ के माध्यम से, निजी क्षेत्रों/विधियों तक पहुंच, * एक ही कक्षा के भीतर * कभी भी अनुमति नहीं दी जानी चाहिए। (जो दयालु है। मैं कोई जेएलएस विशेषज्ञ नहीं हूं, लेकिन मैं तुरंत नहीं देख सकता कि यह क्यों नहीं होना चाहिए।) संक्षेप में, जेडीके 1.6 कंपाइलर में एक बग था। – Paul

+1

@ पॉल कोई समस्या नहीं, दिलचस्प पोस्ट के लिए धन्यवाद। यदि आप रुचि रखते हैं तो मेरा संपादन देखें। –

+4

बहुत अच्छा जवाब! शोध करने और व्याख्या करने के लिए धन्यवाद। – Jesse

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