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

本文探讨了《Java编程思想》中关于类的包访问权限解释的疑惑,并通过实验验证了类的访问权限与包外访问的关系,强调了public与protected成员在包外的不可访问性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类的包访问权限:《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编程思想》那段话应该是错误的,至少说应该是有歧义的。(手上没有英文原版,所以原版是怎么描述的,不大清楚)
  2、具有包访问权限的类,包外的类是不可以调用,无论是一般的方法、字段,还是静态方法及字段。
  3、具有包访问权限的类,其成员声明为public和protected是没有意义的,因为在包外不能访问也不能继承的。

  再顺便提一句,在很多书中,都说如果类的成员是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));      
  }
}


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

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值