2014-12-11 41 views
6

我今天在我們的Android代碼庫中發現了這個問題,讓我的同事感到困惑。我們以前有一類結構如下所示:在不同版本的Android中受保護的內部類可見性差異

Foo.java

package test.a; 

public abstract class Foo extends View { 
    protected abstract class InnerFoo { 
     public InnerFoo() {} 
    } 
    protected class Cog { 
     public Cog() {} 
    } 
} 

Bar.java

package test.a; 

public class Bar extends Foo { 
    private abstract class AbstractInnerBar extends InnerFoo { 
     protected abstract void someMethod(); 
    } 
    private class InnerBar extends AbstractInnerBar { 
     Cog myCog; 
     public InnerBar() { 
      myCog = new Cog(); 
     } 
     protected void someMethod() {} 
    }   
} 

我明白這個類的結構不一定簡單,但它的工作沒有問題。不過,我們最近做了一些包重組,並意識到Bar在別的地方。所以,我們把它移到了不同​​的包裏,幾乎有相同的結構,有兩個不同的包。

Foo.java

package test.a; 

public abstract class Foo extends View { 
    protected abstract class InnerFoo { 
     public InnerFoo() {} 
    } 
    protected class Cog { 
     public Cog() {} 
    } 
} 

Bar.java

package test.b; //This is the only change 

public class Bar extends Foo { 
    private abstract class AbstractInnerBar extends InnerFoo { 
     protected abstract void someMethod(); 
    } 
    private class InnerBar extends AbstractInnerBar { 
     Cog myCog; 
     public InnerBar() { 
      myCog = new Cog(); 
     } 
     protected void someMethod() {} 
    }   
} 

奇怪的是,在變更後的一些 Android版本,我們得到這樣的錯誤:java.lang.IllegalAccessError: tried to access class test.a.Foo$Cog[] from class test.b.Bar$InnerBar。我不認爲這會是一個問題,因爲Cog給出protected知名度,Bar extends FooInnerBar延伸InnerFoo。奇怪的是,其他版本的Android工作正常(沒有錯誤,沒有可見性問題)。我們能夠通過宣佈Cogpublic來解決問題,但這似乎是一種不必要的解決方法。

我們在運行Android 4.4.4的摩托羅拉Moto X(第一代開發版)上看到了這個問題。我們在運行Android 4.1.2的Nexus 5上運行Lollipop或Nexus S時沒有問題。誰能說明這一點?

+0

如果您在部署APK之前清理項目,還會出現錯誤嗎? – 2014-12-11 03:00:23

+0

乾淨後仍然會出現錯誤。我甚至有一位同事在他的機器上製作一個APK,在他的手機上運行(Nexus 5/Lollipop),然後adb在Moto X/KK上安裝相同的APK,並且它崩潰。 – loopyzort 2014-12-11 20:18:18

回答

0

程序包a中的抽象類Foo是默認的程序包私有,您應該將其訪問說明符更改爲public以避免任何錯誤。 否則Cog類應該沒有問題,即使它受到保護。只要讓Foo公開,你就可以走了。

public abstract class Foo{} 
+0

謝謝瓦倫,趕上!不幸的是,當我輸入問題時,這是一個翻譯錯誤(我用Foo/Bar示例替換了我們的源代碼)。我們的代碼實際上將Foo類聲明爲「public abstract」。我已經在原始問題中更新了源代碼。 – loopyzort 2014-12-11 17:59:51

+0

如果您將Foo聲明爲公共,而Cog是Foo的受保護成員並且由Bar繼承,那麼它應該沒有任何問題,因此它仍然在Bar中受到保護。但是,由於它在moto x上顯示了一個錯誤,所以它完全出乎意料。 – varun 2014-12-11 19:28:56

相關問題