类的包访问权限:《Java编程思想》中一段话的困惑

来源:互联网 发布:仿mac桌面软件 编辑:程序博客网 时间:2024/05/16 18:13

原文链接:点击打开链接

类的包访问权限:《Java编程思想》中一段话的困惑

在《java编程思想第三版》(陈昊鹏 饶若楠等译)的第五章隐藏具体实现中,5.4节的最后一段话是:

“正如前面所提到的,如果没能为类访问权限指定一个访问修饰符,它就会缺省得到包访问权限。这意味着该类的对象可以由包内任何其他类来创建,但包外则是不行的。(一定要记住,相同目录下的所有不具有明确package声明的文件,都被视作是该目录下缺省包的一部分。)然而,如果该类的某个static成员是public的话,则客户端程序员仍旧可以调用该static成员,尽管他们并不能生成该类的对象。”

刚开始我对最后一句话的理解是:如果某个类没有指定访问修饰符,但其中有static成员是public的话,在包外的类中仍然可以调用该类的static的public方法或访问static的public成员字段。

于是我做了下面的实验:(我的classpath没有设置,是默认值,即是当前路径;我CMD的当前路径Thinking in java。)
在Thinking in java/chapter5/下有Test.java,代码如下

package chapter5;class Test{    public static int i=0;    public static void print(){    System.out.println("class Test public static procedure");    }    public void println(){    System.out.println("class Test public procedure");    }}
在Thinking in java/下有Test1.java,代码如下
import chapter5.*;public class Test1 {public static void main(String[] args) {int a;a = Test.i;// Test.print();}}


接着,编译Test1.java,结果编译器报错,说Test类不是公开类,不可以调用其方法或访问其成员字段。


结论:

1、《Java编程思想》那段话应该是错误的,至少说应该是有歧义的。(手上没有英文原版,所以原版是怎么描述的,不大清楚)

原文: However, if a static member of that class is public, the client programmer can

still access that static member even though they cannot create an object of that class.

2、具有包访问权限的类,包外的类是不可以调用,无论是一般的方法、字段,还是静态方法及字段。

3、具有包访问权限的类,其成员声明为public和protected是没有意义的,因为在包外不能访问也不能继承的。

注:我也在困惑这个问题, 但这个在包访问权限的类里定义public方法还是有意义的。
其意义在于继承类对方法的调用上。
如果类A 定义成了 包访问权限:
里面两个方法f1(){} 和 public f2(){}

类 B 为public 并继承自A.(在同一包里)。
public class B extends A
在A里调用 超类的f1()和f2()都可以。

类C 继承自类B,(在不同包里)在C里可以调用f2(),但不能调用f1()l了。


再顺便提一句,在很多书中,都说如果类的成员是public的,那么无论是谁,无论在哪里,都可以访问该成员的。这种说法其实是不准确的,因为它有个前提,那就是那类必须是public。

Ps:我只是个初学者,这是我自己的总结,如果有错误,请高手斧正。

附Julysea评论

下面是我做的测试,和原文的代码稍有出入

Test.java

package javaforum.inner;class Test {public static final int PUBLIC_STATIC_NUMBER = 100;static int DEFAULT_STATIC_NUMBER = 200;public int PUBLIC_NUMBER = 300;protected int PROTECTED_NUMBER = 400;private int PRIVATE_NUMBER = 500;}
========================================
Main.java

package javaforum;import java.lang.reflect.Field;public class Main {public static void main(String[] args) throws Exception {Class clazz = Class.forName("javaforum.inner.Test");Field field1 = clazz.getField("PUBLIC_STATIC_NUMBER");// 被注释掉的语句根本就不能通过编译// Field field2 = clazz.getField("DEFAULT_STATIC_NUMBER");Field field3 = clazz.getField("PUBLIC_NUMBER");// Field field4 = clazz.getField("PROTECTED_NUMBER");// Field field5 = clazz.getField("PRIVATE_NUMBER");// 没有下面一句,程序编译没问题,执行会报错field1.setAccessible(true);System.out.println(field1.getInt(null));field3.setAccessible(true);// 虽然上面一句没报错,可是下面一句仍然不可以执行System.out.println(field3.getInt(null));}}

楼主,你最后那注释掉的几行,用getDeclaredField()就可以取到private和其他Field了。
Java的反射还是很强大的。


可以看到的是利用java的反射机制,确实可以办到作者的意图。而且,也只能到public staic 为止,其他存取限定下的数据,用反射也是不可以取到的。似乎原来的翻译中“仍旧可以调用”改为“仍然能够存取”,可能更好。


0 0