1.包的定义及使用
包的本质实际上就属于一个文件夹,在项目开发中很难避免类名称重复的问题,如果所有的java文件都放在一个文件夹中,就有可能存在覆盖问题
1.1.包的导入
开发中使用包的定义之后,相当于把一个大的项目分别按照一定要求保存在了不同的包之中,但是这些程序类一定会发生互相调用的情况,这个时候就需要包的导入
类使用class和public class的区别:
- public class: 文件名称必须与类名称保持一致,如果
希望一个类被其他包访问
,则必须定义为public class - class: 文件名称可以与类名称不一致,在一个*.java中可以定义多个class,但是
这个类不允许被其他包所访问
需要注意的是,导入的语句为"import 包.类"这样只会导入一个类,如果说现在导入一个包中的多个类,可以直接采用通配符"*“来完成,这种”*"并不意味要将包中的所有类都进行导入,而是根据你的需求来导入
不同包但是相同类名的情况,这个时候如果还是直接使用类就会产生一个编译上的歧义,这个时候我们一般在使用时使用全名称定义
1.2.系统常用包
java.lang
:系统常用基础类(String、Object),此包从JDK1.1后自动导入
java.lang.reflect
:java 反射编程包- java.net:进行网络编程开发包
- java.sql:进行数据库开发的支持包
java.util:是java提供的工具程序包(集合类等)
java.io:IO编程开发包
- java.awt(离不开windows平台)、java.swing:UI开发包,主要进行界面开发包,目前已经不用了
1.3.访问控制权限
在java 中提供有四种访问控制权限:
private<default<protected<public
,这四种访问控制权限的定义如下:
对于public永远都可以访问,对于封装性而言主要是private、default、protected权限,在不同包中,只有子类能访问父类中的protected权限
关于权限选择:
- 对于封装的描述90%使用private,只有10%会使用protected,这两个都叫封装
- 属性都使用private,方法都使用public
2.jar命令
jar本质上也是一种压缩文件
,里面保存的都是*.class
文件。也就是说现在要实现某一个功能模块,可能有几百个类,最终交付给用户使用时,为了方便管理,就会将这些文件形成压缩包提供给用户。在JDK中提供实现jar文件操作的命令,只需要输入一个jar即可。对于此命令,有如下几个常用参数:
- “c”:创建新档案
- “f”:指定档案文件名
- “v”:在标准输出中生成详细输出
编译源文件并打包:
public class Message {
public void print() {
System.out.println("Hello I am Message");
}
}
对上述源文件编译而后变为jar文件:
- 打包进行程序编译:javac -d . Message.java
- 将生成的程序类打包为jar文件:jar -cvf Message.jar Message.class
打开后发现有一个META-INF文件夹,里面包含版本号等信息,此时的Message.jar就包含我们需要的程序类
要想使用jar文件,并不是说将其放到程序的目录之中就可以,还需要配置CLASSPATH
,设置jar文件的加载路径才会起效,开发中会使用大量的jar文件,所有的jar文件必须配置在classpath中
3.单例设计模式&多例设计模式
3.1.单例设计模式
所谓的单例设计:
- 一个类只允许产生一个实例化对象
- 此实例化对象由自己产生
- 仅提供给其他对象这唯一实例
3.2.饿汉式单例(上来就new)
class Singleton{
//在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
private final static Singleton INSTANCE = new Singleton() ;
//私有化构造
private Singleton() {
}
//静态方法返回一个对象
public static Singleton getInstance() {
return INSTANCE ;
}
}
饿汉式单例:
线程安全
耗费资源
- 适用于单例对象占用资源少
3.3.懒汉式单例(用时再new)
class Singleton{
private static Singleton instance ;
//私有化构造
private Singleton() {
}
//静态方法返回一个对象
public static Singleton getInstance() {
if (instance==null) {
// 表示此时还没有实例化
instance = new Singleton() ;
}
return instance ;
}
}
懒汉式单例:
- 第一次调用时才初始化。在并发情况下可能new出多个实例
线程不安全
- 但是不耗费资源
3.4.懒汉式单例的优化(双重检查)
public class Singleton{
//私有该实例和构造方法
private static volatile Singleton instance;
private Singleton(){}
//双重检查
public static Singleton getInstance(){
//检查此时是否new了
if(null == instance){
//锁住类对象,保证只有一个对象进入代码块
synchronized(Singleton.class){
//确保是第一次new操作
if(null == instance){
instance = new Singleton();
}
}
}
return instance;
}
}
volatile在此的作用:禁止指令重排,因为new一个对象会有三部操作:
- 堆上分配空间
- 属性初始化
- 引用指向对象
此处使用volatile防止指令重排new出残疾实例
实际上单例最靠谱的方式是通过枚举,因为枚举单个元素本身就是单例,这样可以有效防止通过反射、反序列化等手段破坏单例,由JVM从根本上保证,至于多例模式,该概念已经被枚举代替
4.异常体系
4.1.受查异常与非受查异常
先来看一下异常的继承类结构:
- Error:描述Java运行时内部错误与资源耗尽错误。这种内部错误一旦出现,除了告知用户并使程序安全终止以外,再无能为力。
- Exception(程序出错):
- IOException:程序本身没问题,由于IO处理导致的程序错误
- RuntimeException:由于程序错误导致的
非受查异常
(无需强制处理):继承于Error或RuntimeException(空指针异常,类型转换异常,数组越界异常)的异常类称为非受查异常受查异常
(必须强制处理):直接继承于Exception与IOException的称为受查异常
4.2.异常处理格式
try{
有可能出现异常的语句 ;
}[catch (异常类 对象) {
} ... ]
[finally {
异常的出口
}]
对于以上三个关键字,可以出现的组合:try…catch、try…finally、try…catch…finally,出现了异常之后,由于存在异常处理机制,依然可以正常执行完毕,还可以调用所有异常类中提供的printStackTrace()方法进行完整异常信息的输出,注意:有finally块时,无论try catch中是否有返回语句,最终都会执行finally块
4.3.throws关键字(作用在方法上)
在进行方法定义的时候,如果要告诉调用者本方法可能产生哪些异常
,就可以使用throws方法进行声明,如果该方法出现问题后不希望进行处理,就使用throws抛出
,如果现在调用了throws声明的方法,那么在调用时必须明确的使用try…catch…进行捕获,因为该方法有可能产生异常,所以必须按照异常的方式来进行处理,主方法本身也属于一个方法,所以主方法上也可以使用throws进行异常抛出,这个时候如果产生了异常就会交给JVM处理
4.4.throw关键字(作用在方法内)
thorw是直接编写在语句之中,表示人为进行异常的抛出
,如果现在异常类对象不希望由JVM产生而由用户产生实例,就可以使用throw来完成
解释throw和throws的区别:
throw用于方法内部,主要表示手工异常抛出
throws主要在方法声明上使用,明确告诉用户本方法可能产生的异常,同时该方法可能不处理此异常
4.5.RuntimeException类
很多的代码上都可能出现异常,例如"10/0"都可能产生异常,如果所有可能产生异常的地方都强制性异常处理,这个代码就太复杂了。所以在异常设计的时候,考虑到一些异常可能是简单问题, 所以将这类异常称为RuntimeException,也就是使用RuntimeException定义的异常类可以不需要强制性进行异常处理
请解释Exception与RuntimeException的区别,请列举几个常见的RuntimeException:
Exception是RuntimeException的父类,使用Exception定义的异常都要求必须使用异常处理,而使用RuntimeException定义的异常可以由用户选择性的来进行异常处理
- 常见的RuntimeException:ClassCastException、NullPointerException等
5.断言
- 启动断言需要使用-ea参数传给虚拟机,手工开启,默认不开启断言
- AssertionError:断言异常(错误)->非受查异常