包是一个文件夹,它是类的一种特殊的性质,可以更合理地管理大量的类文件,设置他人对类成员的访问权等。
在用 Java 开发大型项目时,通常要把类分门别类地存到文件里,再将这些文件一起编译执行,这样的程序代码将更易于维护。同时在将类分割开之后,对于类的使用也就有了相应的访问权限。
1.包( package )的基本概念
所谓的包( package )指的就是一个文件夹,即在不同的文件夹之中可以保存同名的类文件。
包的使用方法:在类或接口的最上面一行加上 package 的声明。通常包全部用小写字母命名。
package 的声明方法如下。
package paceage名称[.package名称2.package名称3……];
程序中如果有 package 语句,该语句一定是源文件中的第一条可执行语句,它的前面只能有注释或空行。另外,一个文件中最多只能有一条 package 语句。
经过 package 的声明之后,同一文件内的接口或类就都会被保存在相同的 package 中。
包的名字有层次关系,各层之间以点分隔。包层次必须与 Java 开发系统的文件系统结构相同。
若包声明如下:package java.awt.a,则文件中的接口和类都存放在 …java\awt\a 目录下。
举例:
//package的使用
package demo.java; //声明package
class Person
{
public String talk()
{
return "Person→talk()";
}
}
class TestPackage
{
public static void main(String[] args)
{
System.out.println(new Person().talk());
}
}
2.包的导入
使用包可以将功能相似的若干类保存在一个文件目录之中,但是这样一来就有可能出现包之间的互相访问问题,当一个程序需要其他包中类的时候可以通过 import 完成导入操作。package 导入的方法如下:
import package 名称.类名称;
若某个类需要被访问时,则必须把这个类公开出来,即此类必须声明成 public。通过 import 命令,可将某个 package 内的整个类导入,后续程序可直接使用类名称,而不用再写上被访问的 package 的名称。
若在不同的 package 中存在相同类名的 public 类,若要访问某个 public 类的成员时,在程序代码内必须明确地知名 “ 被访问package的名称.类名称 ”。
如:
package demo.java.a; //声明package
public class Person
{
public String talk() //类中的方法
{
return "Person→talk()"; //返回一串字符串
}
}
//声明一个 demo.java.b包,并调用demo.java.a中的类方法
package demo.java.b;
import demo.java.a.Person;
//将demo.java.a包中的Person类导入到此包之中
class TestPackage2
{
public static void main(String[] args)
{
//调用demo.java.a中的方法并输出
System.out.println(new Person().talk());
}
}
如果说一个项目之中有几百个类时,为了方便导入可以使用 “ 包.* ” 的形式完成。虽然使用的是 “ 包.* ” ,但实际上并不表示此包之中的所有类都会被导入,导入的时候也只能是导入所需要的类,不需要的类是不会有任何加载的,所以分开导入和使用 “ * ” 导入从性能上讲是完全一样的。
另外,上述程序也可写成如下形式:
//包的导入使用
package demo.java.b;
class TestPackage3
{
public static void main(String[] args)
{
//在程序中将写出所用类的具体位置
System.out.println(new demo.java.a.Person().talk());
}
}
在程序中没有使用 import 语句,但是在语句中使用 Person 类的时候使用了 “ 包名.类名 ” 的方式,在程序中也可以使用此方法来使用非本类所在的包中的类。
很多时候有可能在程序开发之后导入的包里面有同名的类,则这个时候再使用类的话就必须写上类的完整名称 “ 包名.类名 ” 才可以正常操作。
3.JDK 中常见的包
SUN 公司在 JDK 中为程序开发者提供了各种实用类,这些类按功能不同分别被放入了不同的包中,供开发者使用。下面简要介绍其中最常用的几个包。
(1)java.lang:包含一些 Java 语言的核心类,如 Sring、Math、Integer、System 和 Thread,提供常用功能。在 java.lang 包中还有一个子包:java.lang.reflect,用于实现 java 类的反射机制。
(2)java.awt:包含构成抽象窗口工具集( abstract window toolkits )的多个类,这些类被用来构建和管理应用程序的图形用户界面( GUI )。
(3)avax.swing :此包用于建立图形用户界面,包中的组件相对于 java.awt 包而言是轻量级组件。
(4)java.applet :包含 applet 运行所需的一些类。
(5)java.net :包含执行与网络相关的操作的类。
(6)java.io :包含提供多种输入/输出功能的类。
(7)java.util :包含一些实用工具类,如定义系统特性、与日期日历相关的方法。
在 Java 1.2 以后的版本中,java.lang 这个包会自动被导入,对于其中的类,不再需要使用 import 语句来做导入,如经常使用的 System 类。
举例:
//导入一个Applet程序所需要的包
package demo.java; //声明包demo.java
import java.applet.*; //导入java.applet中所有包
import java.awt.*; //导入java.awt中所有包
public class MyApplet extends Applet
{
public void paint(Graphics g)
{
g.drawString("Hello", 30, 30); //输出一行字
g.drawLine(50, 50, 100, 100); //画一条线
}
}
Applet 程序必须继承一个 Applet 类,Java 是单继承局限,所以此程序肯定不会再用了。Applet 程序和之前所编写的 Application 程序有一个最大的区别:Applet 不是依靠主方法运行,而 Application 是依靠主方法运行的,Applet 已经成为了一个过去。
在 Java 中有 4 种访问控制权限,分别为 private、default、protected、public。
1.private 访问控制符
如果一个成员方法或成员变量名的前面使用了 private 访问控制符,那么这个成员只能在这个类的内部使用。
2.default 默认访问控制符
如果一个成员方法或成员变量名前面没有使用任何访问控制符,就称这个成员所拥有的是默认的( default )访问控制符。默认的访问控制成员可以被这个包中的其他类访问。如果一个子类与其父类位于不同的包中,子类也不能访问父类中的默认访问控制成员。
3.protected 访问控制符
如果一个成员方法或成员变量名前面使用了 protected 访问控制符,那么这个成员既可以被同一个包中的其他类访问,也可以被不同包中的子类访问。
4.public 访问控制符
如果一个成员方法或成员变量名前面使用了 public 访问控制符,那么这个成员可以被所有的类访问,不管访问类与被访问类是否在同一个包中。
综上,用下表总结如上 4 个权限:
private | default | protected | public | |
同一类 | √ | √ | √ | √ |
同一包中的类 | √ | √ | √ | |
不同包中的类 | √ | √ | ||
其他包中的类 | √ |
举例:
//protected关键字的使用
package demo.java.a; //声明包demo.java
public class Person
{
protected String name; //声明该变量为protected属性
public String talk() //类中的方法
{
return "Person→talk()"; //返回一串字符串
}
}
//编译会报错
package demo.java.b; //声明包demo.java
import demo.java.a.*; //导入Person类
public class Student extends Person //Student类继承自Person类
{
public Student(String name)
{
//Student类访问Person类中的name属性
this.name = name;
}
public String talk() //类中的方法
{
return "Person→talk(),"+this.name; //返回一串字符串
}
}
//编译会报错
package demo.java.c; //声明包demo.java
import demo.java.b.*; //导入Person类
public class TestPackage
{
public static void main(String[] args)
{
Student s = new Student("java");
s.name = "Hello Java!"; //通过对象调用受保护的属性
System.out.println(s.talk());
}
}
变量使用 protected 关键字声明时,此属性只能在本类及其子类中使用。如果其他类通过对象调用受保护的属性,程序在编译时 JDK 就会报错。
通过查阅 JDK 文档,可以看到,JDK 中类的声明、方法的声明、常量的声明等都是有一定规律的。
(1)包中的字符一律小写,如 demo.java。
(2)类名、接口应当使用名词,每个单词的首字母大写,如 TestPerson。
(3)变量名( 属性名 )第 1 个单词小写,后面的每个单词首字母大写,如 newPerson。
(4)方法名的第 1 个单词小写,后面每个单词的首字母大写,如 talkPerson()。
(5)常量名中的每个字母一律大写,如 PERSONNUM。
jar 文件即 Java archive file( Java存档文件 )的缩写,其应用与 Java 息息相关。jar 文件就是一种压缩文件,与常见的 ZIP 压缩文件格式兼容,习惯上称之为 jar 包。如果开发者开发了许多类,当需要把这些类提供给用户使用时,通常都会将这些类压缩到一个 jar 文件中,以 jar 包的方式提供给用户使用。只要别人的 classpath 环境变量的设置中包含这个 jar 文件,Java 虚拟机就能自动在内存中解压这个 jar 文件,把这个 jar 文件当做一个目录,在这个 jar 文件中去寻找所需要的类名及包名所对应的目录结构。
jar 命令是 Java 中提供的一个非常有用的命令,可以用来对大量的类( .class 文件 )进行压缩,然后存为 .jar 文件。那么通过 jar 命令所生成的 .jar 压缩文件又有什么优点呢?一方面,可以方便管理大量的类文件,另一方面,进行了压缩也减少了文件所占的空间。对于用户来说,除了安装 JDK 之外什么也不需要做,因为 SUN 公司已经帮开发者做好了其他的一切工作。
在命令行窗口下( Win + R 输入 cmd 按回车 )运行 jar.exe 程序,只要在命令行中使用以下命令就可以将一个包打成一个 jar 文件。
jar -cvf create.jar demo
-c :创建新的存档。
-v :生成详细输出到标准输出上。
-f :指定存档文件名。
create.jar :是生成 jar 文件的名称。
demo :要打成 jar 文件的包。
举例:
//自动生成的构造方法的类
package demo.java.d; //声明包demo.java
class Singleton
{
public void print()
{
System.out.println("Hello World.");
}
}
实际上现在在 Singleton 类之中是存在构造方法的,并且这个构造方法是午餐的,什么都不做的,自动生成的构造方法,可以再主类中对其进行实例化。
//实例化对象
package demo.java.d; //声明包demo.java
public class TestInstance
{
public static void main(String[] args)
{
Singleton instance = null; //声明对象
instance = new Singleton(); //实例化对象
instance.print();
}
}
现在将代码 Singleton.java 变换一下,将构造方法明确定义,但是权限变为 private。
private Singleton(){} //此时的类中不会再生成余灿的什么都不做的构造
那么现在构造方法 Singleton() 被声明为 private 类型,只能在类内部访问。那如何在不修改 Singleton 类的构造方法以及 print() 方法的前提条件下,Singleton 类之中应该增加什么样的操作,才可以让主类得到 Singleton 类实例化对象,并且调用 print() 方法输出呢?
现在所有的问题都在于构造方法上使用了 private 进行定义,private 的访问特点:只能够在本类中使用,所以现在可以尝试着在类中实例化属于自己的对象。
举例:
//实例化属于自己的对象
package demo.java.d; //声明包demo.java
class Singleton
{
static Singleton instance = new Sinleton(); //实例化对象
//此时的类中不会再生成无参的什么都不做的构造
private Singleton(){}
public void print()
{
System.out.println("Hello World.");
}
}
public class TestSinleton
{
public static void main(String[] args)
{
Singleton instance = null; //声明对象
instance = Singleton.instance; //实例化对象
instance.print(); //调用方法输出问候信息
}
}
类之中的所有属性只有在调用构造方法实例化对象之后才会分配空间,那么现在外部无法调用 Singleton 类的构造方法,所以依靠外部是不可能的,就必须从内部的 instance 定义上想办法,有没有一种方法可以让 Singleton 在没有实例化对象的时候就去操作 instance 呢?自然可以想到使用 static 定义。
可是针对于类之中所有定的属性都会有一个明确的要求,必须使用 private 封装,那么一旦封装之后,如果此时还希望可以在没有实例化对象的时候取得 instance 属性,就必须利用 static 方法返回。
如下:
//单例设计模式
package demo.java.d; //声明包demo.java
class Singleton
{
static Singleton instance = new Sinleton(); //实例化对象
//此时的类中不会再生成无参的什么都不做的构造
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
public void print()
{
System.out.println("Hello World.");
}
}
public class TestSinleton
{
public static void main(String[] args)
{
Singleton instance = null; //声明对象
instance = Singleton.instance; //实例化对象
instance.print(); //调用方法输出问候信息
}
}
如果要想产生类的实例化对象,那么一定要调用构造方法,如果把一个类的构造方法卡死了,那么就表示外部无法调用此构造,就意味着外部无法产生实例化对象。
同时在类内部定义的本类实例化对象使用的是 static 定义,static 的特点是在全局数据区之中保存,是一个公共属性,那么这样一来,不管在外部声明了多少个对象,那么实际上只是取得了唯一的一个实例化对象,所以这样的设计在设计模式上被称为单例设计模式。
但是以上的代码编写实际上也存在一个问题,既然现在希望表示只有唯一的一个实例化对象,那么为了避免内部的对象会被重复实例化,所以最好加上一个关键字 final 定义。
单例设计模式是只能够存在一个实例化对象,而多例设计模式指的是一个类可以定义指定多个对象,但是不管是单例还是多例,构造方法都不可能使用 public 定义。
实际上对于多例设计能够体现在很多的方面,例如:现在要定义一个表示一周时间数的类,那么这个类只能够有七个对象。如果定义一个表示性别的类,那么这个类只能有两个对象。例如表示颜色基色的类只有三个对象,这些都属于多例设计模式。
举例:
//多例设计
package demo.java.d; //声明包demo.java
class Sex //性别
{
private String title; //保存信息
private static final Sex MALE = new Sex("男");
private static final Sex FEMALE = new Sex("女");
private Sex(String title)
{
this.title = title;
}
public static Sex getInstance(int ch) //static方法
{
switch(ch){
case 0:
return MALE;
case 1:
return FEMALE;
default:
return null;
}
}
public String toString()
{
return this.title;
}
}
public class TestMultiton
{
public static void main(String[] args)
{
System.out.println(Sex.getInstance(0));
}
}
1.封装性需要通过三个权限来实现:private、default、protected。但是面对个人开发,常用的权限就只有两个。
(1)只要是定义属性不用思考直接写上 private;
(2)只要是定义方法不用思考直接写上 public。
2.什么是设计模式?
在进行程序设计时,逐渐形成的一些典型问题和问题的解决方案,这就是软件模式;每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案;当我们遇到模式所描述的问题,就可以直接用相应的解决办法去解决这个问题,这就是设计模式。
设计模式就是抽象出来的东西,它不是学出来的,是用出来的;或许我们根本不知道任何模式,不考虑任何模式,却写着最优秀的代码,即使以 “ 模式专家 ” 的角度来看,都是最佳的设计,不得不说是 “ 最佳的模式实践 ”,这是因为我们积累的很多的实践经验,知道 “ 在什么场合代码应该怎么写 ”,这本身就是设计模式。
3.多例设计模式的特点如下。
(1)多例类可以有多个实例。
(2)多例类必须能够自我创建并管理自己的实例,并向外界提供自己的实例。
(3)根据是否有实例上限分为:有上限多例类和无上限多例类。
4.Java 包的使用技巧( 如何在 Eclipse 中导入 jar 包 )。
首先右击项目选择【Build Path】→【Configure Build Path...】,在打开的窗口中,选中【Libraries】,再从右边的按钮中点击
【add JARs...】然后选中 jar 包,然后点击【OK】关闭窗口。此时,我们在刚才打开的【Libraries】页中可以看到我们引入的jar包的名称,点击【OK】确认即可。