概述
访问权限控制
关于java中的访问权限控制,需要先理解以下几个概念:
(1)编译单元:当我们编写出一个java源代码文件时,这个文件就被称为编译单元(或转译单元),这个编译单元的后缀名为.java。在编译单元内则可以有一个public类和多个非public的类,但是如果有public类的话,编译单元的名字必须和public类的名字一致,否则编译时会报错。如果此编译单元内没有public类的话,编译单元的名字就无所谓了。
(2)类文件:当编译一个.java文件(编译单元)时,在.java文件中的每一个类都会有一个输出文件,该输出文件的名称与.java文件中每个类的名称相同,只是多了一个后缀.class。每一个.java文件编译后生成的这些.class文件集合称为类文件。所以,每一个.java文件编译后都会得到一个类文件,这个类文件中包含了大量的.class文件。
(3)类库:类库就是一组类文件的集合。每一个类文件中都包含了一个public类以及任意数量的非public类。
思考一个问题:如果类名称冲突了怎么办?比如我自己写了一个A类需要加载到一台机器上,但是这台机器上已经有别人写好的另外一个A类,这时该如何处理呢?这时就引出了包的概念。
包:关键字为package,包的出现完美的解决了类名冲突的问题,把具有相同类名,但有可能具有不同功能的类放置于不同的包里,这样当我们需要使用某类时,通过指定不同的包,从而区别出应该正确调用的类。
(4)包:类库单元,包中管理组织了类库中一部分类文件,不同的包中管理着不同的类文件,从而将类库完美的区分开来。如果在java编译单元中使用package语句,那么它必须位于编译单元的除注释外的首行。例如在文件起始处写:package access;那么它表示你在声明该编译单元是名为access的类库的一部分。或者说你正在声明的该编译单元中的public类名称是位于access名称的保护伞下,任何想要使用该名称的人都必须在使用前给出选择,指定全名或与access结合使用import导入。
java中的访问权限:java中为什么需要访问权限控制呢?思考以下2个场景:
场景1:工程师A编写了一个类ClassA,但是工程师A并不希望ClassA被该应用中其他所有的类都访问到,那么该如何处理?
场景2:如果工程师A编写了一个类ClassA,其中有两个方法fun1、fun2,工程师只想让fun1对外可见,也就是说,如果别的工程师来调用ClassA,只可以调用方法fun1,那么该怎么处理?
此时,访问权限控制便可以起到作用了。在Java中,提供了四种访问权限控制:默认访问权限(包访问权限),public,private以及protected。
一.修饰类
修饰类的话,只能有2个关键字来修饰
默认访问权限(包访问权限):用来修饰类的话,表示该类只对自己和同一个包中的其他类可见。常见的就是源文件中的非public类。
public:用来修饰类的话,表示该类对其他所有的类都可见。
验证一下:
AccessControlTestForClass类位于sixthchaptertest包中,虽然导入进来了,但是我们看一下它:
类是默认访问权限的,所以只能在sixthchaptertest包中被访问到,所以会报上面图中的错误。当我们把它改成public修饰时,一切正常。
二.修饰类的方法和变量
默认访问权限(包访问权限):如果一个类的方法或变量被包访问权限修饰,也就意味着只能在同一个包中的其他类中显示地调用该类的方法或者变量,在不同包中的类中不能显示地调用该类的方法或变量。
private:如果一个类的方法或者变量被private修饰,那么这个类的方法或者变量只能在该类本身中被访问,在类外以及其他类中都不能显示地进行访问。
protected:如果一个类的方法或者变量被protected修饰,对于同一个包的类,这个类的方法或变量是可以被访问的。对于不同包的类,只有继承于该类
的类才可以访问到该类的方法或者变量。
public:被public修饰的方法或者变量,在任何地方都是可见的。
测试一下各个内容
1.默认访问权限的变量和方法
同包中定义2个public的类:
AccessControlTestForVarAndMethord类中定义一个变量a和方法f(),它们都是包访问权限的,在AccessControlTestForClass中调用它们,看看结果:
结果正常调用,输出为:
再在包外的AccessControlTest中调用看看
可以看到我们定义的重载构造器本身也没有加任何访问权限修饰符,那么这个构造器本身就是包访问权限的,所以,在包外无法调用,我们将构造器改成public修饰,然后再调用它的变量和方法,看看出现什么结果:
可以看到编译器都报出错误:说变量a和方法f()均不是public访问权限,所以不能引用于包外因此验证成功。
2.private修饰变量和方法
这里将变量a和方法f()改为private修饰:
同包中的其他类访问时的结果:
不同包中的类的访问结果:
2个报错均提示变量a和方法f()为private修饰,无法在外部类中使用,验证成功
3.protected修饰变量和方法
同理,将变量a和方法f()改成protected修饰,先测试一下同包中的类的访问结果:
同包中的其他类正常访问。
不同包的其他类(非子类)访问结果:
可以看到,不同包的其他类(非子类)无法访问到。
在其他包中定义一个AccessControlTestForVarAndMethord类的子类
这里,子类可以正常访问,打印的结果为:
此时,a为什么会是0呢?
因为子类AccessControlTest01并没有定义重载的构造器,那么,在创建子类对象时,会调用子类的默认构造器,因为子类继承了父类,在调用子类的构造器之前会默认先调用父类的默认构造器,父类中的默认构造器并没有对int类型的a进行初始化,那么a就会自动初始化为0,如果父类中没有定义默认构造器,或者说父类中定义了一个重载的有参构造器,编译器就不会自动帮父类生成默认的构造器,那么因为父类没有默认构造器就会报错。我们注释掉父类的默认构造器:
然后创建子类继承父类时:
编译器报错说父类中没有定义默认构造器。那么解决方式可以是在父类中显式定义出默认构造器,或者在子类中显式定义出默认构造器,并在构造器的首行显式调用父类的重载构造器,如下图所示:
这样做后,编译成功,再看输出结果:
a被正确的初始化了。
再来看一个问题:如下图所示
在子类中创建了一个父类对象,父类对象的变量a和方法f()是protected修饰的,按理来说,不是在子类中可以调用的吗?这个问题的原因在于:在子类中可以调用父类的protected修饰的字段和变量的调用方是谁?调用方是子类,也就是子类的对象才可以调用父类的
protected修饰变量和方法,而不是在子类中父类对象可以调用它的protected修饰的变量和方法。所以说:
protected:如果一个类的方法或者变量被protected修饰,对于同一个包的类,这个类的方法或变量是可以被访问的。对于不同包的类,只有继承于该类的子类对象才可以访问到该类的方法或者变量。
4.public修饰的变量和方法
public修饰的变量和方法并没有什么限制,在任何地方都可以访问到,这里不再做出演示。
最后
以上就是怕孤独心锁为你收集整理的java基础-访问权限控制的全部内容,希望文章能够帮你解决java基础-访问权限控制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复