包 - Java基础知识 14

目录

包的定义与使用

包的导入

包的静态导入

Jar命令

系统常用包

访问控制权限


学习笔记

在实际大项目来开发过程之中,我们肯定一直存在包的概念,利用包可以实现类的包装,在以后的实际开发之中,所有的类都必须放在包里面。

包的定义与使用

对于项目而言,尤其是现代项目是不可能有一个人开发完成的,往往在一个项目的开发团队中会有2-3位的开发者进行项目业务的一个实现,那么不得不面对的问题:有可能产生类的重名定义。

在操作系统之中已经严格明确定义了一个要求:同一个目录下不允许存放有相同的程序类文件。但是在程序开发中很难保证类的不重复,所以为了方便管理,往往将程序文件放在不同的目录下,不同的目录之中可以提供相同文件的,这个目录称之为包。包==目录。

范例:包的定义

package cn.ren.demo ; // 定义包,其中.表示分割子目录(子包)
public class Hello{
	public static void main(String arges []){
		System.out.println("Hello World !") ;
	}
}

一旦程序开发之中有了包,此时程序编译的结果就必须将*.class的文件保存在指定的目录之中,但是手工建立麻烦,此时最好的做法是进行打包编译处理:javac -d . Hello.java

  • “-d” :表示要生成的目录,而目录的结构就是package定义的结构;
  • ".":表示在当前所在的目录中生成程序类文件;

在程序执行的时候一定要带着包执行程序类:java cn.ren.demo.Hello,也就是说完整的类名称:“包.类”名称。

包的导入

利用包的定义就可以将不同功能的类保存在不同的包之中,但是这些类之间一定存在有互相调用的关系,那么这个时候就需要使用import语句来导入包之中的其它程序类。

范例:定义一个程序类“cn.ren.util.Message”,这个类负责进行一个消息数据的获取。

package cn.ren.util ;
public class Message{
	public String getContent(){
		return "Hello Ren" ;
	}
}

范例:定义一个类使用Message类“cn.ren.test.TestMessage”。

package cn.ren.test ;
import cn.ren.util.Message ; // 导入其他包的类
public class TestMessage{
	public static void main(String args){
		Message msg = new Message() ;  // 实例化类对象
		Syatem.out.println(msg.getContent()) ;
	}
}

此时按照顺序来讲,肯定先编译Message.java,然后在编译TestMessage.java,但是有一个程序代码,里面有一百个类彼此之间引用严格,就怎么区分?最好方法是交给Java自己完成,编译命令:javac  -d . *.java; *.java表示自己匹配顺序。

注意:public class 与 class 的区别?

  • public class : 类名称必须与文件名称保持一致,一个*.java 中只允许有一个public class,同时如果一个类需要被其它的所使用,那么这个类一定要定义为public class;

  • class :类名称可以与文件名称不一致,并且在一个*.class可以提供多个class定义,编译后将形成不同*.class文件,但是这些类只能够被本包所访问,外包无法访问。 

  • 在实际的开发之中,往往在一个*.Java源代码文件中,里面只会提供一个程序类,而这个程序类一般使用public class 定义。程序类中定义的包名称,只能够使用小写字母的形式定义。

但是这个时候,会有一个问题产生,有些时候会使用包中的很多类,于是这样进行分开类的导入会比较麻烦,为了解决这样的问题,可以使用通配符“*”进行处理。

package cn.ren.test ;
import cn.ren.util.* ; // 导入其他包的类

即便此时使用了“ 包.* ”的导入形式,那也不表示要进行全部的加载,他会根据自己的需要加载所需要的程序类,而不需要的程序类不会加载的,所以使用*还是具体的程序类其最终的性能是完全相同的。

但是如果在开发之中采用的是“包.*”的形式进行包的导入使用,那么有一点会比较麻烦:有可能俩个不同的包中存在相同的类名称,例如,Test Message类由于某种需要要导入两个包:cn.ren.util、org.demo,但是这两个包里面都有Message类,如下:

package org.demo ;
public class Message{
	public String getInfo(){
		return "人民万岁" ;
	}
}
package cn.ren.util ;
public class Message{
	public String getContent(){
		return "Hello Ren" ;
	}
}

由于某种需要在TestMessage中需要导入两个包,如下:

package cn.ren.test ;
import cn.ren.util.Message ; // 导入其他包的类
import org.demo.* ;
public class TestMessage{
	public static void main(String args[]){
		Message msg = new Message() ;  // 实例化类对象
		System.out.println(msg.getContent()) ;
	}
}

程序编译:

这个时候发现类名称相同的时候就会出现,类名称引用不明确。所以此时最简单的形式就是写上类的完整名称。如下:

cn.ren.util.Message msg = new cn.ren.util.Message() ;  // 实例化类对象

在日后的开发过程中经常会见到大量的重名类(包不重名),此时最好的解决方法使用用类的完整名称。

包的静态导入

假如说现在有一个,这个类中的所有方法都是static方法,那么按照原始做法肯定要导入程序所在的“包.类”,而后可以通过类名称调用这些静态方法。

范例:定义一个MyMath数学类

package cn.ren.util ;
public class MyMath{
	public static int add(int ... arges){
		int sum = 0;
		for(temp : arges){
			sum += temp ;
		}
		return sum ;
	}

	public static int sub(int x, int y){
		return x - y;
	}
}

所有的方法都是stati方法, 如果此时按照原始的方式导入处理,那么此时就需要导入包.类,而后通过类名称调用方法。

范例:原始方式

package cn.ren.test ;

import cn.ren.util.MyMath ;
public class TestMath{
	public static void main(String args[]){
		System.out.println(MyMath.add(10,20,30,40,50)) ;
		System.out.println(MyMath.sub(10,20)) ;
	}
}

从JDK1.5开始,对于类中全部由静态方法提供特殊类是可以采用静态导入处理形式的。

范例:静态导入处理

package cn.ren.test ;
import static cn.ren.util.MyMath.* ;
public class TestMath{
	public static void main(String args[]){
		System.out.println(add(10,20,30,40,50)) ;
		System.out.println(sub(10,20)) ;
	}
}

当使用了静态导入处理之后,该方法就像直接定义在主类中的,可以使用主方法进行调用。

一般不采用

Jar命令

当一个项目开发完成之后,一定会存在大量的*.class文件,那么对于这些文件的管理往往可以使用压缩结构形式来处理,而这样的结构在Java之中就被称为Jar文件,如果要想将程序打包成jar文件,可以利用程序中的jar命令完成。

在最原始的时候,要想知道jar命令的直接使用,直接输入jar即可,而在jdk1.9之后为了统一化,使用jar -- help可以知道相关说明。

 

 

下面通过程序的具体演示,实现jar的使用与配置的操作。

1、定义一个程序类,这个类的代码如下

package cn.ren.util;
public class Message{
	public String getContent(){
		return "hello !" ;
	}
}

2、对程序进行编译与打包处理

  • 对程序编译: javac -d . Message.java。
  • 此时会形成cn的包,包里面有相应的子包与*.class文件,将其打包为ren.jar: jar -cvf ren.jar cn

          |- "-c" :创建一个新的jar文件

          |- “-v” :得到详细输出 ;

          |- “-f” :设置要生成的jar文件的名称,本处定义的是"ren.jar"

3、每个*.jar文件都是一个独立的程序路径,如果要想在Java之中使用此路径,则必须通过CLASSPATH进行配置:

SET CLASSPATH=.;d:\renjava\ren\ren.jar

4、建立测试类,直接导入Message类并且调用方法

package cn.ren.test ;
import cn.ren.util.Message ; // 导入其他包的类
public class TestMessage{
	public static void main(String args[]){
		Message msg = new Message() ;  // 实例化类对象
		System.out.println(msg.getContent()) ;
	}
}

随后就可以正常编译TestMessage类并且使用这个类。

  • 编译:javac -d . TestMessage.java
  • 解释:java cn.ren.test.TestMessage

如果此时编译通过之后,由于CLASSPATH发生了改变,类无法加载到了,则执行TestMessage后将会出现如下的错误提示:

Exception in thread "main" java.lang.NoClassDefFoundError: cn/ren/util/Message

出现这种错误只有一中情况:  *.jar包没有配置正确

JDK1.9之后出现的模块化操作:

  • 在jdk1.9以前实际上是提供的一个所有类的*.jar文件(rt.jar、tools.jar),在传统的开发之中,只要启动了Java虚拟机,那么就需要加载这几十兆的类文件;
  • 在jdk1.9之后提供了模块化的设计,将原来很大的需要加载的*,jar文件变成了若干个模块文件,这样在启动的时候可以根据程序加载指定的模块(包),实现启动速度变快的效果。

系统常用包

Java语言从发展至今提供了大量的类库,这些类库一般有两个方面组成:

  • Java自身提供的(除了jdk提供的类库之外还会哟一些标准),
  • 由第三方厂商提供的Java支持类库,可以完成需要的功能,并且支持的厂商很多

而在JDK之中也会提供大量的类库,并且这些类库都封装在不同的开发包之中的:

  • java.lang: String、Number、Object等都在里面,这个包在JDK1.1之后默认导入;
  • java.lang.reflect: 反射机制处理包,所有的设计从此开始;
  • java.util: 工具类的定义,包括数据结构的定义;
  • java.io: 输入与输出流操作的程序包;
  • java.net:网络开发程序包;
  • jvava.sql: 进行数据库编程的开发包;
  • java.applet: Java最原始的使用形式,直接嵌套在网页上直接执行的程序类;

            | - 现在的程序主要以Application为主(有主方法的程序);

  • java.awt、java.swing: Java图形界面开发包(GUI),其中awt是重量级组件,swing是轻量级的组件。

访问控制权限

在面向对象的开发过程之中有三大特点:封装、继承、多态。那么对于封装性而言,主要的实现的依靠是访问控制权限,而访问控制权限在程序之中一共定义有四种:private、default、protected、public,这四种权限的作用如下:

 访问范围private default protectedpublic
1同一包中的同一类
2同一包中的不同类
3不同包的子类 
4不同包的所有类  

在整个访问的控制权限之中,只有protected(受保护)的权限是一个比较新的概念。下面进行说明,本次定义两个类:

  • cn.ren.a.Message : 提供protected访问权限。

  • cn.ren.b.NetMessage :将直接访问protected属性。

范例:定义子类

package cn.ren.a;
public class Message{
	protected String info = "hello" ;
}

范例:定义子类,与父类不在一个包中

package cn.ren.b ;
import cn.ren.a.Message ;
public class NetMessage extends Message{
	public void print(){
		System.out.println(super.info) ;
	}
}

范例:编写测试类,通过子类实现操作

package cn.ren.test ;
import cn.ren.b.*
public class TestMessage{
	public static void main(String args[]){
		new NetMessage().print() ;
	}
}

此时程序通过子类访问父类中的protected属性。但是此时直接通过Message访问属性,那么就会出现错误的提示。

范例:在测试类中直接访问Message的属性。


package cn.ren.test ;

import cn.ren.a.* ;
public class TestMessage{
	public static void main(String args[]){
		System.out.println(new Message().info) ;
	}
}

在程序之中的封装一共定义有三种范文权限:private、default、protected,但是如果每次在使用的时候进行区分很麻烦。给出参考的选择方案(90%的问题):

  • 只要进行属性定义,使用private
  • 只要是进行方法的定义,使用public

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值