2014-12-11 42 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

相关问题