# Java模块封装
# 包
面向对象的核心组成是类和接口,在项目中会利用包进行类的分组管理,包的概念有点像文件系统中的文件夹概念,这样会比较适合代码的更新与组织:
blog目录中的Tools.java内容为:
package cn.tools.blog;
public class Tools{
public void GetUI(){
System.out.println("get user ui!");
}
public static void main(String args[]){
System.out.println("this is class Tools in cn.tools.blog!");
}
}
2
3
4
5
6
7
8
9
10
business目录中的Tools.java内容为:
package cn.tools.business;
public class Tools{
public void GetBusiness(){
System.out.println("get business logic!");
}
}
2
3
4
5
6
测试主程序test.java为:
//import cn.tools.blog.Tools;
import cn.tools.blog.*;
import cn.tools.business.*;
public class test{
public static void main(String[] args){
cn.tools.business.Tools t1 = new cn.tools.business.Tools();
t1.GetBusiness();
}
}
2
3
4
5
6
7
8
9
注意几个地方:
- 如果现有的目录结构是按着包的结构排列的,可以使用javac *.java 来进行按需,且按照依赖顺序编译。
- 在编译有包定义的java文件时,像Tools.java这样的文件,如果要按包的定义生成目录,可使用javac -d . *.java。
- 在对包名称进行命名时要求所有的字母都得是小写。在包中定义的类要想被其他包中的类使用,需要声明为public类。
- 在导入时,使用import packageName.*并不影响性能,这样也只是导入所需的类,不需要的并不导入。
- 同时使用import导入不包中的相同类名时,需要使用时加上全类名。
# 静态导入
当一个类中的所有方法都是static时,可以利用JDK1.5提供的静态导入操作。
CommonFunc.java文件:
package cn.tools.math;
public class CommonFunc {
public static void Add(int a,int b) {
System.out.println(a+"+"+b+"="+(a+b));
}
public static void Sub(int a,int b) {
System.out.println(a+"-"+b+"="+(a-b));
}
public static void Div(int a,int b) {
System.out.println(a+"/"+b+"="+(a/b));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
测试主类:
import static cn.tools.math.CommonFunc.*;
public class Main {
public static void main(String[] args) {
Add(1, 2);
Sub(6, 5);
Div(6,3);
}
}
2
3
4
5
6
7
8
9
# jar文件
jar(Java Archive)是Java给出的一种压缩格式文件,可以将很多*.class文件以jar包方式给用户,更方便维护。
有几个参数需要了解:
参数 | 说明 |
---|---|
-c | 创建一个jar包 |
-t | 显示jar中内容列表 |
-x | 解压jar包 |
-u | 添加文件到jar包 |
-f | 指定jar包的文件名 |
-v | 输出详细报告 |
-m | 指定MANIFEST.MF文件 |
-0 | 生成jar包时不压缩内容 |
-M | 不生成清单文件MANIFEST.MF |
-i | 为指定jar文件创建索引 |
-C | 在相应的目录下执行命令 |
它的命令格式为:
jar {c t x u f }[ v m e 0 M i ][-C 目录]文件名...
其中ctxu是必选其一,vme0Mi是可选可不选。来看几个常用命令:
打jar包:
jar -cvf target.jar folder
打jar包,但不生成清单,不压缩:
jar -cvfM0 target.jar cn
解压jar包:
jar -xvf target.jar
往jar包添加文件:
jar -uf target.jar addedFileName
打出jar包后需要在classpath中明确包含该jar包才能使用。
# 常用系统包
包名称 | 作用 |
---|---|
java.lang | 基本包,包含像String这样的基础常用类,JDK1.0的时候需要手动导入,后面是自动导入。 |
java.lang.reflect | 反射机制相关,是java.lang的子包。 |
java.util | 工具包,常用的类库和日期操作都在该包。 |
java.text | 文本处理类库。 |
java.sql | 数据库操作包。 |
java.net | 网络编程。 |
java.io | 输入,输出处理。 |
java.awt | 构成抽象窗口工具集(abstract window toolkits),用来构建和管理应用程序的GUI。 |
javax.swing | 用于建立GUI,相对java.awt来说相对轻量。 |
java.applet | 在浏览器端运行java。 |
在JDK1.9之前,JDK提供包含所有的*.jar文件,比如rt.jar和tools.jar,只要启动了Java虚拟机就需要加载这些类文件。在JDK1.9之后,提供了一个模块化的设计,将原本加载jar文件变成了若干个模块文件,这样根据程序中指定的模块加载相应的类,提高加载速度。
# 访问控制权限
Java中共有四种访问权限:
范围 | private | default | protected | public |
---|---|---|---|---|
同一包的同一类 | 可访问 | 可访问 | 可访问 | 可访问 |
同一包的不同类 | 不可访问 | 可访问 | 可访问 | 可访问 |
不同包的子类 | 不可访问 | 不可访问 | 可访问 | 可访问 |
不同包的非子类 | 不可访问 | 不可访问 | 不可访问 | 可访问 |
一般属性是以private为主,方法以public为主。
# 构造方法私有化
在类结构中,每次使用new 对象名,就会调用构造方法并实例化新的对象,可利用这点来实现实例化对象的控制。
# 单例设计模式
该模式指的是整个系统中一个类只允许提供一个实例化对象,通过将构造方法私有化来实现,这样可以在系统中提供一个全局实例化对象供用户利用。
# 饿汉单例
public class Singleton {
private static final Singleton Instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return Instance;
}
public void printInfo() {
System.out.println("this is singleton class!");
}
}
2
3
4
5
6
7
8
9
10
11
12
# 懒汉单例
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if(instance== null) {
instance = new Singleton();
}
return instance;
}
public void printInfo() {
System.out.println("this is singleton class!");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 加锁懒汉
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
return instance;
}
public void printInfo() {
System.out.println("this is singleton class!");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 双重加锁懒汉
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
public void printInfo() {
System.out.println("this is singleton class!");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 内部静态类
public class Singleton {
private static Singleton instance;
private Singleton() {
}
private static class InnerClass{
static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return InnerClass.instance;
}
public void printInfo() {
System.out.println("this is singleton class!");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 模式对比
模式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
饿汉 | 简单方便,不管是否使用了单例对象都会生成单例对象 | 由于该静态对象是在类加载时生成,会降低应用的启动速度 | 类对象比较简单,占内存小 |
懒汉 | 在需要单例对象时才去构造单例对象,可以提高应用启动速度 | 线程不安全,多个线程同时获取单例对象时可能会生成多个单例对象 | 类对象比较复杂,占内存多 |
加锁懒汉是为了解决懒汉的线程安全问题,双重加锁懒汉是为了在内部已经单例实例化了之后直接获取即可,不用再判断线程安全。
内部静态类则是使用单例对象时才去加载,并且是线程安全的,这样实现简单还能懒加载,线程安全。
# 多例设计模式
多例跟单例的原理基本一致,但是是根据传入参数来返回不同的对象:
public class Multiton {
private static final Multiton class1 = new Multiton("计算机");
private static final Multiton class2 = new Multiton("英语");
private static final Multiton class3 = new Multiton("数学");
private String infoStore;
private Multiton(String info) {
this.infoStore = info;
}
public static Multiton getInstance(String info) {
switch (info) {
case "english":
return class2;
case "math":
return class3;
case "cs":
return class1;
default:
return null;
}
}
public String toString() {
return this.infoStore;
}
}
public class Main {
public static void main(String[] args) {
Multiton m1 = Multiton.getInstance("cs");
Multiton m2 = Multiton.getInstance("english");
Multiton m3 = Multiton.getInstance("math");
System.out.println(m1);
System.out.println(m2);
System.out.println(m3);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 枚举
Java从最开始并没有提供枚举,当时很多使用多例来代替枚举,从JDK1.5开始,Java支持了枚举定义:
enum MyColor{
RED,GREEN,BLUE
}
public class Main {
public static void main(String[] args) {
MyColor c1 = MyColor.RED;
System.out.println(c1);
for (MyColor color:MyColor.values()) {
System.out.println(color);
System.out.println(color.ordinal()+"-"+color.name());
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
枚举本身并不是一种新类型,跟String类一样,枚举对应的类是java.lang.Enum,每一个使用enum定义的类都继承了Enum类。
# 定义枚举结构
枚举也可以定义成员属性,构造方法,普通方法,但是本质上它属于多例,不允许使用public定义构造方法。如果没有无参构造方法,那么定义每个枚举时必须明确传入参数。
enum MyColor{
RED("red"),BLUE("blue"),GREEN("green");
private String colorString;
private MyColor(String color) {
this.colorString = color;
}
@Override
public String toString() {
return this.colorString;
}
}
public class Main {
public static void main(String[] args) {
System.out.println(MyColor.RED);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 枚举类实现接口
interface IGetColorInfo{
public String getColor();
}
enum MyColor implements IGetColorInfo{
RED("red"),BLUE("blue"),GREEN("green");
private String colorString;
private MyColor(String color) {
this.colorString = color;
}
@Override
public String getColor() {
return colorString;
}
}
public class Main {
public static void main(String[] args) {
System.out.println(MyColor.RED.getColor());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 枚举定义抽象方法
枚举可直接进行抽象方法的定义,在每一个枚举对象中分别实现抽象方法。
enum MyColor {
RED("red"){
@Override
public String getColor() {
return "颜色信息:";
}
},BLUE("blue"){
@Override
public String getColor() {
return "蓝色";
}
},GREEN("green"){
@Override
public String getColor() {
return "绿色";
}
};
private String colorString;
@Override
public String toString() {
return colorString;
}
private MyColor(String color) {
this.colorString = color;
}
public abstract String getColor() ;
}
public class Main {
public static void main(String[] args) {
System.out.println(MyColor.RED.getColor());
System.out.println(MyColor.BLUE.getColor());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33