JAVA基础编程——包和访问控制权限

在C/C++中,是通过.h文件和.cpp文件进行功能区分的,通常一个.cpp文件会对应一个.h文件,而如果不同模块之间需要进行交互操作,或者需要进行接口调用的话,就需要包含对应的.h文件,以表示当前的模块包含了对应模块,因此就可以调用对应模块的接口了。而JAVA中只存在一种.java文件,因此便通过包和包管理实现了这种功能。

在JAVA中,可以将大型的类进行独立,不同功能分别保存到不同的包中,然后将所有包中的程序文件进行编译执行,这样产生的代码便会更易于维护。

在JAVA中,源程序文件是.java文件,而.java文件经过编译后都保存在同一个目录中,因此在大型项目中,很可能会发生同名覆盖的问题,因为大型项目编译后很难保证不存在重名文件。而如果要想解决同名文件冲突的问题,就必须要设置在不同的目录。而所谓的包就是指不同的文件夹,这样就能够保证不存在重名文件。在JAVA中使用package关键字来定义包,同时该语句必须写在.java文件的首行。

package com.wood.demo;

public class Demo {
    public static void main(String args[]) {
		System.out.println("Hello world");
	}
}

上面的代码会在当前路径下生成com/wood/demo/Demo.class文件。不过在生成文件之前需要经过打包编译,存在两种打包编译方法:

  • 打包编译:javac -d path xxx.java
    • -d表示生成目录,根据package的定义生成
    • path表示保存的路径
  • 在解释程序的时候在包外输入类的完整名称
    • 指令为:java com.wood.demo.Demo;

在实际开发中,为了方便程序的管理,所有的类都一定要放在一个包中,而完整的类名永远都是“包.类”,同时没有包的类最好不要在开发中出现。

包的导入

使用包可以将一个完整的程序拆分为不同的文件进行保存。而既然存在包,就会存在包之间的互相访问,此时就需要进行包的导入。

JAVA中包的导入类似于C/C++中的#include,不过使用的是import,同时import语句必须写在package语句之后,而import语句应该编写在类的定义之前。

package com.wood.util;

public class Message {
    public void fun() {
	    System.out.println("fun");
	}
}

如果定义了上面的类,并构建了对应的包。那么就可以进行导入,并调用相应的方法:

package com.wood.demo;

import com.wood.util.Message;

public class Demo {
    public static void main(String args[]) {
		System.out.println("Hello world");
		
		Message msg = new Message();
		
		msg.fun();
	}
}

结果为:

Hello world
fun

上面的代码中,导入了com.wood.util.Message类,然后便可以实例化Message类对象,调用fun方法了。

同时如果在当前目录存在多个.java文件的话,JAVA编译器考虑到大型项目中可能存在多个.java文件中的类相互引用,为了解决编译顺序的问题,提供了通配符*操作,即:

javac -d path *.java

这样就可以根据代码调用顺序自动进行程序编译。反之如果不使用通配符,就需要按照调用顺序进行手动编译。上边的代码中,也就是需要先编译Message.java,后编译Demo.java。

而如果将上面的Message类定义的public去掉,在编译完Message.java之后编译Demo.java时会出现报错,提示Message类没有使用public class声明,只能在一个包中访问,而外包无法进行访问。也就是说,public class和class声明的类区别在于:

  • public class:文件名必须和类名保持一致,在一个.java文件中只能有一个public class类,如果一个类需要被不同的包访问,就一定要定义为public class
  • class:文件名称可以和类名不一致,并且一个.java文件中可以存在多个class类,此时编译该文件会形成多个.class文件,而如果一个类使用class定义,就表示该类只能被本包访问

而既然编译时存在通配符*的操作,那么导包时便也存在通配符*的操作,此时表示可以导入该包中的所有类:

import com.wood.util.*;

此时表示可以导入com.wood.util包中的所有类。不过在具体使用时,类加载只是加载所需要的类,不使用的类不会被加载。

系统常见包

C/C++中提供了大量的内置接口,JAVA类似地也提供了大量的程序开发包。除了JAVA内置的,也存在许多第三方提供的开发包。常用的包有:

  • java.lang:基本包,如String这样的类就保存在该包中,不过现在该包都是自动导入的
  • java.lang.reflect:反射机制的包,是java.lang的子包
  • java.util:工具包,一些常用的类库、日期操作等都在该包中
  • java.text:文本的处理类库
  • java.sql:数据库操作包,提供了各种数据库操作的类和接口
  • java.net:网络编程相关的包
  • java.io:输入、输出及文件处理操作
  • java.awt:包含抽象窗口工具集的多个类,这些类可以用来构建和管理应用程序的GUI
  • javax.swing:用于建立GUI,不过相对于java.awt包而言则是轻量级组件
  • java.applet:小应用程序开发包

jar

C/C++中,提供给用户的文件既可以是源文件,也可以是编译打包后的库文件。与C/C++库文件对应的就是JAVA中的jar包。

JAVA中,如果项目中存在大量的.class文件,如果.class文件过多,则会显得结构过于臃肿。此时可以使用jar命令对.class文件进行压缩,实际开发中,交付给用户的也是java归档(JAVA Archive, jar)文件,也就是jar包。

JDK默认提供了生成jar包的工具(jar.exe),可以在命令行直接使用,相关参数为:

  • -c:创建一个新文件
  • -v:生成标准的压缩信息
  • -f:由用户指定生成的.jar文件名称

比如之前的Message.java文件可以使用jar.exe进行打包:

jar -cvf self.jar com

上面的命令可以将生成的com目录(包的根目录)打包成一个压缩的jar包在本地目录。不过生成的jar包并不能直接使用,必须配置CLASSPATH才能够被其它程序类正常加载使用。

访问控制权限

C/C++中存在三种权限,分别是private/protected/public,而在JAVA中存在四种权限:

范围privatedefaultprotectedpublic
在同一包的同一类yesyesyesyes
同一包的不同类yesyesyes
不同包的子类yesyes
不同包的非子类yes

上表可以理解为:

  • private只能在一个类中访问
  • default只能在一个包中访问
  • protected可以在不同包的子类中访问
  • public则都可以

对于protected权限来说,可以定义下边的代码:

package com.wood.demoA;

public class DemoA {
    protected String info = "Hello";
}

以及:

package com.wood.demoB;

import com.wood.demoA.DemoA;

public class DemoB extends DemoA {
    public void fun() {
	    System.out.println("DemoA info is " + super.info);
	}
}

执行代码:

package com.wood.demo;

import com.wood.demoB.DemoB;

public class Demo {
    public static void main(String args[]) {
		new DemoB().fun();
	}
}

结果为:

DemoA info is Hello

因为是protected修饰的info,因此才可以在包外的子类中访问。

不过对于访问权限,只需要了解两个原则:

  • 属性声明主要使用private权限
  • 方法声明主要使用public权限

命名规范

JAVA中的命名规范主要包括:

  • 类名称:每一个单词的开头首字母大写
  • 变量名称:第一个单词的首字母小写,之后每个单词的首字母大写
  • 方法名称:第一个单词的首字母小写,之后每个单词的首字母大写
  • 常量名称:每个字母都大写
  • 包名称:每个字母都小写

单例设计模式

单例设计模式是一种基本的设计模式,用JAVA语言可以实现为:

class Singleton {
    private static final Singleton instance = new Singleton();
	
	private Singleton() {
	}
	
	public static Singleton getInstance() {
	    return instance;
	}
	
	public void fun() {
	    System.out.println("Singleton");
	}
}

public class Demo {
    public static void main(String args[]) {
		Singleton inst = Singleton.getInstance();
		inst.fun();
	}
}

结果为:

Singleton

这里解释下程序:

  • instance前的private表示该属性不可直接在类外访问,需要通过getInstance方法获得该属性
  • instance前的static则是由于getInstance方法为static,static方法只能调用static属性和static方法
  • instance前的final则是为了防止重复实例化Singleton对象,避免重复申请空间
  • Singleton构造方法前的private是为了避免在类外实例化Singleton对象
  • getInstance方法前的static则是为了可以在类外获得Singleton实例,这也是获得单例对象的唯一方法

多例设计模式

多例设计模式则是相对于单例设计模式而言的,对于只能构建固定个数的类来说,不应构建超过该个数的实例对象,比如性别,颜色,性别等。为了防止无限制地构建实例化对象,可以使用多例设计模式。

class Sex {
	private String title;
	private static final Sex MALE = new Sex("Male");
	private static final Sex FEMALE = new Sex("Female");
	
	private Sex(String title) {
		this.title = title;
	}
	
	public String toString() {
	    return this.title;
	}
	
	public static Sex getInstance(String str) {
		switch (str) {
		    case "male":
			    return MALE;
			case "female":
			    return FEMALE;
			default:
			    return null;
		}
	}
}

public class Demo {
    public static void main(String args[]) {
		Sex inst = Sex.getInstance("male");
		System.out.println(inst.toString());
	}
}

结果为:

Male

上面的代码中则可以通过传入参数判断实例化的对象,而由于只存在两种Sex实例对象,因此便称为多例设计模式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值