十二,包与权限相关知识

血红的双手。 提交于 2021-02-02 21:54:52

1.包的定义

包(package)是Java提供的一种区别类的名字空间的机制,是类的组织方式,是一组相关类和接口的集合,它提供了访问权限和命名的管理机制.实际上就是一个文件夹,在不同的文件夹中可以存在同名的类.

语法: package aaa.bbb.ccc ;

Java中提供的包主要有以下3种用途:

  • 将功能相近的类放在同一个包中,可以方便查找与使用.

  • 由于在不同包中可以存在同名类,所以使用包在一定程度上可以避免命名冲突.

  • Java,某次访问权限是以包为单位的.

打包之后的类,实际上就是包路径.类名称了.

有了打包,自然就有了导包的操作,关键字是import.需要注意的一点只有public class才能被外包类引用.导包中也可以用*来表示导入该目录下的需要使用的类.它不会影响性能,而具体到类名的性能是一样的.

:导入其他类的时候可能出现重名的情况,这时实例化操作的时候会报错,正确的操作是写完整的包.类名来实例化对象.

2.静态导入

要使用静态成员(方法和变量)我们必须给出提供这个静态成员的类.使用静态导入可以使被导入类的静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出他们的类名.静态导入也是JDK1.5引入的新特性.

用法: import static语句导入一个类中的某个静态成员(方法或属性)或所有静态成员.

示例:

//导入Math类中的所有static方法和属性. 
//这样我们在使用这些方法和属性时就不必写类名. 
import static java.lang.Math.*;
//import static java.lang.Math;//这样写报错  
public class StaticImport { 
       public static void main(String[] args) { 
//            System.out.println(Math.max(3, 5));//没有使用静态导入 
//            System.out.println(Math.abs(1-9));//没有使用静态导入 
              System.out.println(max(3, 5)); 
              System.out.println(abs(1-9)); 
       }




3.系统常用包

java.lang 包含了各种常用的类,此包属于自动导入.

java.lang.reflect 此包为反射机制包,java中非常重要,可以完成大量的底层操作.

java.util 工具包,如果把此包掌握的非常清楚,会非常方便的进行各种设计和开发.

java.io IO操作的包

java.net 网络编程常用的包

java.sql 数据库编程常用的包

java.text 国际化程序的应用,提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口.

4.访问权限

Java有四种访问权限, 其中三种有访问权限修饰符,分别为private,publicprotected,还有一种不带任何修饰符.

private
Java
语言中对访问权限限制的最窄的修饰符,一般称之为“私有的”.被其修饰的类、属性以及方法只能被该类的对象访问,其子类不能访问,更不能允许跨包访问.

default
即不加任何访问修饰符,通常称为“默认访问模式“.该模式下,只允许在同一个包中进行访问.

protect
介于public private 之间的一种访问修饰符,一般称之为“保护形”.被其修饰的类、属性以及方法只能被类本身的方法及子类访问,即使子类在不同的包中也可以访问.

public
Java
语言中访问限制最宽的修饰符,一般称之为“公共的”.被其修饰的类、属性以及方法不仅可以跨类访问,而且允许跨包(package)访问.

5.命名规范

定义规范的目的是为了使项目的代码样式统一,使程序有良好的可读性.

包的命名:全部小写,由域名定义.

类的命名:单词首字母大写.

方法的命名:首字母小写,字母开头大写.

参数的命名:首字母小写,字母开头大写.

常量的命名:全部大写 ,常加下划线.

Javadoc注释:

示例:


/**

* This is an example of

* Javadoc

* @author darchon

* @version 0.1, 10/11/2002

*/


6.jar命令

6.1 命令用法

jar {ctxu}[vfm0Mi] [jar-文件] [manifest-文件] [-C 目录] 文件名 ...

示例1:将两个class文件存档到一个名为 'classes.jar' 的存档文件中:

jar cvf classes.jar Foo.class Bar.class

示例2:用一个存在的清单(manifest)文件 'mymanifest' foo/ 目录下的所有

文件存档到一个名为 'classes.jar' 的存档文件中:

jar cvfm classes.jar mymanifest -C foo/ .

6.2 ClassNotFound解决方案

在使用java -jar yourJarExe.jar运行打包好的jar应用程序的时候发现应用程序无法找到classpath下设置好的第三方类库的内容(ClassNotFound).

这是由于当使用-jar参数运行的时候,java VM会屏蔽所有的外部classpath,而只以本身yourJarExe.jar的内部class作为类的寻找范围.

方法一、使用Bootstrap Classloader来加载这些类

我们可以在运行时使用如下参数:

  • -Xbootclasspath:完全取代系统Java classpath.最好不用.

  • -Xbootclasspath/a: 在系统class加载后加载.一般用这个.

  • -Xbootclasspath/p: 在系统class加载前加载,注意使用,和系统类冲突就不好了.

win32 java -Xbootclasspath/a: some.jar;some2.jar; -jar test.jar

unix java -Xbootclasspath/a: some.jar:some2.jar: -jar test.jar

win32系统每个jar用分号隔开,unix系统下用冒号隔开

方法二、使用Extension Classloader来加载

你可以把需要加载的jar都扔到%JRE_HOME%/lib/ext下面,这个目录下的jar包会在Bootstrap Classloader工作完后由Extension Classloader来加载.非常方便,非常省心.

方法三、还是用AppClassloader来加载,不过不需要classpath参数了

我们在MANIFEST.MF中添加如下代码:

Class-Path: lib/some.jar

lib是和test.jar同目录的一个子目录,test.jar要引用的some.jar包就在这里面.

然后测试运行,一切正常!

如果有多个jar包需要引用的情况:

Class-Path: lib/some.jar lib/some2.jar

每个单独的jar用空格隔开就可以了.注意使用相对路径.

另:如果META-INF 下包含INDEX.LIST文件的话,可能会使Class-Path配置失效.INDEX.LISTJar打包工具打包时生成的索引文件,删除对运行不产生影响.

方法四、自定义Classloader来加载

这种方法是终极解决方案,基本上那些知名java应用都是那么干的,tomcatjboss等等.

关于ClassLoader的原理和自定义ClassLoader可以参考这篇http://cuixiaodong214.blog.163.com/blog/static/951639820099135859761

总结:

以上四种方法都可以用,特别是程序运行在非常单纯的环境中时.但是,如果是运行在多任务,多应用的环境中时,最好每个应用都能相互独立,第一种和第二种方案都有可能对其他应用产生影响,因此最好就是选择第三种和第四种.

:JVM寻找Class背景知识

JDK 1.2以后,JVM采用了委托(delegate)模式来载入class.采用这种设计的原因可以参考http://java.sun.com/docs/books/tutorial/ext/basics/load.html

归纳来讲:是基于JVM sandbox(沙盒)安装模型上提供应用层的可定制的安全机制.

Java虚拟机(JVM)寻找Class的顺序

1. Bootstrap classes

属于Java 平台核心的class,比如java.lang.String.rt.jar等重要的核心级别的class.这是由JVM Bootstrap class loader来载入的.一般是放置在{java_home}\jre\lib目录下

2. Extension classes

基于Java扩展机制,用来扩展Java核心功能模块.比如Java串口通讯模块comm.jar.一般放置在{Java_home}\jre\lib\ext目录下

3. User classes

开发人员或其他第三方开发的Java程序包.通过命令行的-classpath-cp,或者通过设置CLASSPATH环境变量来引用.JVM通过放置在{java_home}\lib\tools.jar来寻找和调用用户级的class.常用的javac也是通过调用tools.jar来寻找用户指定的路径来编译Java源程序.这样就引出了User class路径搜索的顺序或优先级别的问题.

3.1 缺省值:调用Javajavawa的当前路径(.),是开发的class所存在的当前目录

3.2 CLASSPATH环境变量设置的路径.如果设置了CLASSPATH,CLASSPATH的值会覆盖缺省值

3.3 执行Java的命令行-classpath-cp的值,如果制定了这两个命令行参数之一,它的值会覆盖环境变量CLASSPATH的值

3.4 -jar 选项:如果通过java -jar 来运行一个可执行的jar,这当前jar包会覆盖上面所有的值.换句话说,-jar 后面所跟的jar包的优先级别最高,如果指定了-jar选项,所有环境变量和命令行制定的搜索路径都将被忽略.JVM APPClassloader将只会以jar包为搜索范围.

有关可执行jar有许多相关的安全方面的描述,可以参考http://java.sun.com/docs/books/tutorial/jar/ 来全面了解.

这也是为什么应用程序打包成可执行的jar包后,不管你怎么设置classpath都不能引用到第三方jar包的东西了.





20150416


JAVA学习笔记系列

--------------------------------------------

                    联系方式

--------------------------------------------

        Weibo: ARESXIONG

        E-Mail: aresxdy@gmail.com

------------------------------------------------
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!