这个问题是我学习think in java思考,页面为第四版196面,Exeicise11
首先,我们先来回顾一下,修饰符权限得问题
如图:基础知识就不废话
首先我们先来思考以下问题:
1、创建一个private内部类,让他实现一个public接口,写一个方法,尝试指向此private内部类得实例引用,并将此引用想上转型成接口,通过尝试向下转型,说明此内部类被完全隐藏了~
2、将上面问题改成protected呢。创建一个protected内部类…
3、defult
4、public
一、首先我们来看第一个问题
代码如下:
package innerClass;
/*public class Exercise11 {
public static void main(String[] args) {
}
}
*/
interface Ex11Interface {
void say(String s);
}
class Friend{
private String name = "mao";
public void printName() {
System.out.println(name);
}
}
public class Test {
private Friend f = new Friend();
Friend getFriend() {
return f;
}
private class Inner implements Ex11Interface {
public void say(String s) {
System.out.println(s);
}
/*@Override
public void what() {
// TODO Auto-generated method stub
}*/
}
/*interface Ex11Interface {
void say(String s);
void what();
}*/
Ex11Interface f() {
return new Inner();
}
Inner g() {
return new Inner();
}
Ex11Interface f2() {
return new Inner2();
}
protected class Inner2 implements Ex11Interface {
public void say(String s) {
System.out.println(s);
}
/*@Override
public void what() {
// TODO Auto-generated method stub
}*/
}
public static void main(String[] args) {
}
}
class Ex11 {
public static void main(String[] args) {
Test t = new Test();
t.f().say("hi");
t.f2().say("how are you");
((Test.Inner2)t.f2()).say("2"); //protected 类可以向下转型
//t.g().say("hello "); he type Test.Inner is not visible
System.out.println(t.g()); //但是可以返回他的引用
// Error: cannot find symbol: class Inner:
//((Test.Inner)t.f()).say("hello"); //private 内部类不能向下转型
//测试private对象域
t.getFriend().printName();
}
}
编译结果:
hi
how are you
2
innerClass.Test$Inner@33909752
mao
1
很明显,上面能返回内部类的引用,但是不能访问内部类的属性,否者提示,找不到该类。
首先我们获得到两个信息:1、类中返回的其实都是引用。即使是类中组合情况,将其他类的对象返回,却能访问该引用指向的对象(代码中的Friend就是我测试的例子),为什么呢?.
很明显编译器的工作方式是这样,(此过程没有解析jvm,只是个人对访问权限控制的设想),通过对象引用访问值,如果是基本类型,那不存在什么访问权限啥的,直接输出值,如果对象引用指向的是对象的话,那编译器会通过你的对象引用,访问指向的类.
然后这时候,你前面看得类的权限修饰符起作用了,private的很明显禁止任何外部访问,直接相当于屏蔽了,所以编译器提示找不到该类,而private Friend对象能访问,是因为编译器看得是Friend类!,是defult,所以同包肯定能访问,如果你在另一个包继承了Test就不行了
2
加入是protected修饰的内部类呢,Test.java代码上面有,这里贴上Ex11.java代码
两个java文件是不同包的,因为这样才能隔离protected包含的同包访问权限,问题暴露得更多
代码如下:
package innerClass.Exercise6;
import innerClass.Test;
public class Ex11 {
public static void main(String[] args) {
//The type Test.Inner is not visible
//Test.Inner;
//Test2.Inner2 ti;
}
class Test2 extends Test{
Test.Inner2 i ; //protected修饰得内部类还是可以在子类中调用
//private 修饰ide内部类继续隐藏
//Test.Inner;
}
}
很明显,main里面得 Test.inner和Test.inner2都显示不了,Test.inner是private内部类,完全屏蔽,访问不了很正常,那么Test.inner2是protected,因为是不同包,所以继承得protected显然,不能在此包使用了,只能在继承了Test得Test2类得内部使用。
总结:
内部类得访问权限,也是根据访问修饰符来控制得,但是要调出逻辑误区,即Java中返回得全是引用,java’编译器根据引用来找类,再来看访问权限。
其实java编译器是也没那么灵活,但是是很客观,理性得,只要你顺着逻辑思考,能搞懂java编译器这么工作得!
补充:
定义在域内和方法内的内部类,基本方法都要返回上层接口,因为,出了域内或者方法内就不可视,只能通过接口,然后多态来调用这个内部类!