一、介绍
访问控制权限控制客户端对类的访问权限,提供给客户端不同权限的接口,对整个程序结构和接口与实现都进行支持。
二、详解
1、包
包(Package)基本上写过java语言都熟悉package是什么。package的主要作用,是对类提供一个命名空间。程序员可以将多个类文件放置到同一个package下来组织这些类文件关系。我们可以说一个类是由package+className实现了一个类的唯一标示。
(1)包的声明与使用
因为一个类的可以说是由package加上类文件组成,因此我们在定义一个类是需要类的包定名,也就是给类声明一个命名空间。因此我们在类的第一行代码进行包声明:
package com.wozipa.study.java.access;
包在声明过程中,需要注意的点:
1、使用关键字package声明Java类的package
2、package的声明过程中全部小写
3、package当出现层次关系式,使用点来表示,子包文件夹
当我们使用一个已经定义好的类是,需要使用类全限定名(package + classname)来引入一个类文件。当然我们也可以批量引入某一个包中的所有类。
import com.wozipa.study.java.access.PackageTests;
import com.wozipa.study.java.access.*;
(2)包在类加载时的作用
我们在开发过程中,编译后一个类文件中所有的类定义都会生成一个.class文件,最终我们会将所有的.class文件打包生成一个Jar文件。
当我们在使用一个Jar文件时,首先需要将该Jar至于CLASSPATH环境变量中,JVM虚拟机会自动解析CLASSPATH变量中所有的Jar文件,当load一个class文件时,就会从这些CLASSPATH变量中的Jar文件中获取类文件。类加载器会根据一个类的package,将其转换成相应的文件夹层次关系,例如com.wozipa.study.java.access会转换成com/wozipa/study/java/access,从CLASSPATH的根路径下沿着文件夹层次关系进行查找。
(3)冲突
有时我们会使用两个相同类名称的类,在代码编写过程中就会出现类名冲突,就是说使用这个类名时,编译器不知道该类名指向的是哪一个类文件。这种情况下我们需要通过类的全限定名来告知编译器类的具体路径:
例如下面,当我们使用第二个PackageTests时,需要通过指定全限定名称来指出类的位置。
import com.wozipa.study.java.access.PackageTests;
public class DefaultTests {
public static void main(String[] args)
{
PackageTests tests = new PackageTests();
com.wozipa.study.java.nio.PackageTests tests1 = new com.wozipa.study.java.nio.PackageTests();
}
}
2、Java访问修饰符
Java访问修饰符通过修饰类、属性、方法、构造器等,来控制所修饰的实体的访问权限。Java的访问修饰符一共四个:private、friendly(包默认权限,默认权限),protected和public。
(1)friendly
包访问权限,顾名思义,就是指当一个属性或者方法(包括构造器方法)使用该权限修饰时,这个属性或者方法可以被同一个Package内的其他类直接使用,而其他Package的类将无法直接该属性或者方法。
(2)public
公开访问权限,被public权限修饰符修饰的属性或者方法函数(包括构造器函数)可以被其他任意的客户端程序进行直接访问。
(3)private
私有权限,被private修饰的属性或者方法函数只能在本类(而不是类文件,也就是说类文件中的 其他类也没办法直接访问该类的私有属性或方法)中使用。
例子:当我们对构造函数用private修饰时,其他类就无法通过new方式来创建对象,如果排除反射,这个基本无法被别人初始化,通过这个原理就有了单例模式:
public class Singletom {
public static Singletom singletom = null;
public static Singletom getSingletom()
{
if(singletom == null)
{
singletom = new Singletom();
}
return singletom;
}
private Singletom(){}
}
这里的单例模式只是简单的说明实现原理,完整的单例模式需要更负责的代码,后面会总结单例模式的多种实现方式。
(4)protected
继承关系权限,被protected修饰的属性或者方法能够被子类或者同一个Package的类使用。也就是说protected除了继承关系权限外,还具有包访问权限。
注意:子类中定义的protected,父类无法使用。
(5)访问手段
想要访问一个属性或者方法是,只能通过一下手段:
(1)将该属性或者方法定义为public权限,客户端可以直接访问和使用
(2)将属性和方法定义为protected方法,可以被子类或者同一个Package的类使用。
(3)对属性或方法使用默认权限,同一个Package内的其他类能够被使用。
(4)对属性使用私有方法使,使用访问器(getter)和变异器(setter)进行属性的获取和变更
(6)默认包的权限
当一个类在声明时没有通过package关键字添加包定义,那么这个类就会存在默认包中,而从JDK1.4开始,默认包的中的将无法直接被访问和使用,即默认包中的类即使是public修饰,用户依旧没有办法获取该类的访问。如果想使用默认包中的类时,必须使用反射技术去获取该对象的实例:
public class DefaultTests {
private String name ="default package tests";
@Override
public String toString() {
return name;
}
}
public static void main(String[] args)
{
try {
Class clazz = Class.forName("DefaultTests");
System.out.print(clazz.newInstance().toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
3、接口与实现
访问控制权限经常被称为具体实现的隐藏。把数据和方法包装到类中,以及具体实现的隐藏,通常共同成为封装。从这句话中,封装不简单的包装,而且还有具体属性和方法的访问控制。这样的原因有两个:
(1)我们通过访问控制来定义客户端程序可以访问和不可访问的权限,客户端程序只能访问特定的接口,而逻辑的具体实现通过不可访问全向封装在内部。防止客户端访问一些逻辑内的函数。
(2)通过访问控制权限,客户端只能访问特定接口,当具体实现发生改变时,并不会对客户端程序的接口访问产生任何影响。
因此我们可以总结为:我们通过权限控制,向客户端程序开放特定接口,然后将内部具体实现通过控制权限封装在内部,这样既可以保证客户端程序不会调用不该调用的接口,还可以在内部实现修改时,不会影响到客户端程序。
4、类的访问权限
我们在前面对访问控制进行讲解时,对象都是属性或者方法,下面介绍一下类的访问权限控制。
(1)类文件
1、一个类文件中,允许一个权限为public的类声明和多个默认权限的类声明。
2、类文件中的public修饰的类声明的名称必须与类文件的名称相同,包括大小写
3、类文件可以只声明多个默认权限的类,并且名字不需要与类文件名称相同。
(2)类的权限
类在声明时,只有public和默认权限这两种,没有protected和private。
当我们在将类定义为默认包权限时,类内部的属性和方法的访问权限也就是默认权限,即使是定义了public,也只能被同一个包中的其他类使用。
三、总结
如果有什么错误的地方请帮我指明出来,共勉!